Обеспечение возвращаемого типа для класса, который реализует интерфейс - PullRequest
12 голосов
/ 07 декабря 2011

Как сделать так, чтобы метод getFoo () в реализующем классе возвращал список типов того же реализующего класса.

public interface Bar{
     ....
     List<? extends Bar> getFoo(); 
}

Прямо сейчас класс, реализующий Bar, возвращает объекты любого класса.который реализует Бар.Я хочу сделать его более строгим, чтобы класс, который реализует Bar, возвращал список объектов только своего типа в getFoo ().

Ответы [ 7 ]

17 голосов
/ 07 декабря 2011

К сожалению, это не может быть применено системой типов Java.

Вы можете довольно близко подойти, используя:

public interface Bar<T extends Bar<T>> {
    List<T> getFoo();
}

И тогда ваши реализующие классы могут реализовать это так:

public class SomeSpecificBar implements Bar<SomeSpecificBar> {
    // Compiler will enforce the type here
    @Override
    public List<SomeSpecificBar> getFoo() {
        // ...
    }
}

Но ничто не мешает другому классу сделать это:

public class EvilBar implements Bar<SomeSpecificBar> {
    // The compiler's perfectly OK with this
    @Override
    public List<SomeSpecificBar> getFoo() {
        // ...
    }
}
2 голосов
/ 07 декабря 2011

Ответы interface Bar<T extends Bar<T>> уже здесь верны, но я просто хотел добавить, что если это действительно то, что вы хотите применить, возможно, вы захотите взглянуть на составление своих объектов, а не на использование наследования. Не зная слишком много о ваших классах, он может выглядеть примерно так:

public interface FooGetter<T> {
    List<? extends T> getFoo();
}

public class FooComposer<T extends Bar> {
    ...
    final T bar;
    final FooGetter<T> barGetter;
}

Или это может выглядеть совсем по-другому ... но главное в том, что если вы хотите, чтобы два Ts совпали, композиция может быть ответом.

Конечно, даже это можно обойти, используя необработанные типы ... но, опять же, если кто-то это делает, они просто используют необработанные List, и когда они получают исключения ClassCastException, вы можете безопасно их ударить. :)

2 голосов
/ 07 декабря 2011

Это невозможно в Java, но вы можете спросить, каков вариант использования для принудительного применения этого в интерфейсе.

  • Если вы программируете с интерфейсом (что вы обычно делаете, почему иначеопределить интерфейс) тип не будет известен
  • Если вы программируете для определенного класса, этот поток уже предоставил опции о том, как вы можете реализовать этот конкретный класс для возврата List<itself>.И поскольку вы программируете для этого конкретного класса, компилятор имеет доступ к этому конкретному типу возвращаемого значения и знает об этом
1 голос
/ 07 декабря 2011

Вы должны вывести общее значение для Bar:

public interface Bar<T extends Foo> {
  ...
  List<T> getFoo();
}

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

0 голосов
/ 07 декабря 2011

Как насчет этого:

interface Bar
{
    // everything but getFoo ( ) ;
}

interface FooGetter < T >
{
    List < ? extends T > getFoo ( ) ;
}

interface BarRef < T extends Bar & FooGetter < T > >
{
    T get ( ) ;
}

все, что реализует BarRef, должно реализовывать T, а все, что реализует T, должно иметь соответственно примененный метод getFoo.

0 голосов
/ 07 декабря 2011

Мне понравилось yshavit ответить лучше, но я не мог понять код. Поэтому я постараюсь написать код так, как мне кажется.

interface Bar
{
    // stuff
    // don't bother with the getFoo method
}

interface BarUtils
{
    < T extends Bar > List < ? extends T > getFoo ( T bar ) ;
}
0 голосов
/ 07 декабря 2011

Может быть, вот так

public interface Bar {
     ....
     List<? extends Bar> getFoo(); 
}

public class T implements Bar {
     List<T> getFoo();
}

public class TestClass extends T {};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...