Java-интерфейсы и возвращаемые типы - PullRequest
31 голосов
/ 10 марта 2010

Считайте, что у меня есть следующий интерфейс:

public interface A { public void b(); }

Однако я хочу, чтобы у каждого из классов, реализующих его, был свой тип возврата для метода b ().

Примеры:

public class C { 
  public C b() {} 
}

public class D { 
  public D b() {} 
}

Как бы я определил свой интерфейс, чтобы это было возможно?

Ответы [ 3 ]

48 голосов
/ 10 марта 2010

Если тип возвращаемого значения должен быть типом класса, который реализует интерфейс, то то, что вы хотите, называется F-ограниченным типом :

public interface A<T extends A<T>>{ public T b(); }

public class C implements A<C>{
  public C b() { ... }
}

public class D implements A<D>{
  public D b() { ... }
}

Словом, A объявляет параметр типа T, который будет принимать значение каждого конкретного типа, который реализует A. Обычно это используется для объявления таких вещей, как clone() или copy(), которые хорошо напечатаны. В качестве другого примера, он используется java.lang.Enum для объявления того, что унаследованный метод каждого перечисления compareTo(E) применяется только к другим перечислениям этого конкретного типа.

Если вы будете использовать этот шаблон достаточно часто, вы столкнетесь со сценариями, в которых вам нужно, чтобы this был типа T. На первый взгляд может показаться очевидным, что это 1 , но на самом деле вам нужно объявить метод abstract T getThis(), который реализаторы должны будут тривиально реализовать как return this.

[1] Как отметили комментаторы, можно сделать что-то подлое, например X implements A<Y>, если X и Y будут правильно взаимодействовать. Наличие метода T getThis() делает еще более очевидным, что X обходит намерения автора интерфейса A.

37 голосов
/ 10 марта 2010

Дженерики.

public interface A<E>{
    public E b();
}

public class C implements A<C>{
    public C b(){
        return new C();
    }
}

public class D implements A<D>{
    public D b(){
        return new D();
    }
}

Поиск обобщенных элементов для получения более подробной информации, но (очень) в основном происходит то, что A оставляет тип E вплоть до выражений реализации (C и D).

То есть, по сути, A не знает (и не должен знать), каким может быть E в любой конкретной реализации.

2 голосов
/ 10 марта 2010

Поскольку Java поддерживает ковариантные типы возврата (начиная с Java 1.5), вы можете сделать:

public interface A { public Object b(); }
...