2013-08-26 3 views
7

Я хотел бы создать общий интерфейс для этих двух классов, но я не уверен, как правильно определить дженерики.Создать общий интерфейс, ограниченный собственным классом

public class ThingA implements Thing { 
    public ThingA createCopy(ThingA original); 
} 

public class ThingB implements Thing { 
    public ThingB createCopy(ThingB original); 
} 

Я попробовал это.

public interface Thing<V extends Thing<V>> { 
    public V createCopy(V original); 

} 

Но я все еще могу делать такие вещи, которые нельзя допускать.

public class ThingB implements Thing<ThingA> { 
    public ThingA createCopy(ThingA original); 
} 

ответ

6

Существует не ключевых слов-ключей (а также для параметров методов и декларации возвращаемых значений), и поэтому вы не можете делать именно то, что хотите.

Другими словами, интерфейс позволит гарантировать, что все методы в классе будут использовать согласованные типы, но не ссылаться на сам тип класса.

0

Вы ищете

public interface Thing<V> { 
    public V createCopy(V original); 
} 

? Если нет, можете ли вы более подробно объяснить, что значит для вас «создать общий интерфейс для двух классов»?

+1

Это все еще позволяет ему делать именно то, чего он не хочет. Дженерики не мешают вам использовать только один тип класса, поскольку это будет общая противоположность цели дженериков. – giorashc

1

Это невозможно. И это не то, что для Generics. Дженерики предназначены для типа безопасности, т. Е. Избегают приведения. Если кто-то делает класс ThingB, который каким-то образом реализует Thing<ThingA>, то отлично. Он абсолютно безопасен по типу. Какое тебе дело? Как это мешает тому, что вы делаете?

0

В случае, если вы можете использовать расширение вместо реализации, то вы могли бы сделать это таким образом:

public interface Thing { ... } 
public abstract class Copyable { 
    public final Copyable copy() { 
     Copyable clone = createCopy(); 
     if (clone.getClass() != getClass()) 
      throw new RuntimeException("Copy has wrong type!"); 
     return clone; 
    } 
    protected abstract Copyable createCopy(); 
} 

И затем использовать его как:

public class Test extends Copyable implements Thing { 
    public String content = null; 

    @Override 
    public Copyable createCopy() { 
     Test clone = new Test(); 
     clone.content = this.content; 
     return clone; 
    } 
} 

/*code somewhere*/ { 
    Test t1 = new Test(); 
    t1.content = "Hello world!"; 
    Test t2 = (Test)t1.copy(); 
    System.out.println(t2.content); 
} 

Одна из проблем с этим, является что Copyable не является интерфейсом. Однако это можно использовать без особых усилий, как показано в примере, но используемая проверка класса не поддерживается на уровне языка. Другими словами, абстрактный метод createCopy не ограничивается классом, который он копирует, и все, что зависит от программиста, который расширяет класс Copyable или класс, который его расширяет.

Положительная сторона состоит в том, что если вы вызываете объект .copy(), он должен возвращать объект, такой же, как и сам. Вместо исключения вы можете вернуть null, если хотите. Тогда вы получили хорошее или ничего.

Но, честно говоря, я не совсем понимаю, почему у вашего локального метода createCopy есть параметр. Это может быть то статический метод ... altrough я даже не могу себе представить, что бы в этот блок коды:

static <X extends Thing> X copy(X object) { ... } 

Может вы могли бы сочетать pratice со статическим универсальным методом и результат становится немного более дружественным :

public interface Thing extends Cloneable { 
    public static <X extends Thing> X copy(X thing) { 
     Object clone = thing.clone(); 
     if (clone.getClass() != getClass()) 
      throw new RuntimeException("Copy has wrong type!"); 
     return (X)clone; 
    } 
} 

public class ThingA implements Thing { 
    public Object clone() { ... } 
} 

/*code somewhere*/ { 
    ThingA a1 = new ThingA(); 
    ThingA a2 = Thing.copy(a1); 
} 

Тем не менее, метод клонирования регулируется исключение вместо ограничения языка, но я думаю, что это далеко не лучшее решение.

Смежные вопросы