Интерфейсы Java и типы возврата

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

public interface A { public void b(); }

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

Примеры:

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

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

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

33
задан Pointy 10 March 2010 в 01:15
поделиться

3 ответа

Если возвращаемый тип должен быть типом класса, который реализует интерфейс, тогда то, что вы хотите, называется 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 , но на самом деле вам нужно объявить абстрактный метод T getThis () , который разработчикам придется тривиально реализовать как верните это .

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

49
ответ дан 27 November 2019 в 17:43
поделиться

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

public interface A { public Object b(); }
2
ответ дан 27 November 2019 в 17:43
поделиться

Generics.

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();
    }
}

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

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

37
ответ дан 27 November 2019 в 17:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: