Java универсальный тип

Когда у меня есть интерфейс

public interface Foo<T> {
    T someMethod();
}

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

Например:

public class Bar implements Foo<Bar>  {
    Bar someMethod() {
        return new Bar();
    }
}
7
задан vrm 29 January 2010 в 22:24
поделиться

4 ответа

Да, это можно сделать (вроде как; см. ниже). (В мире С++ это называется "Curiously Recurring Template Pattern", но это относится и к Java):

public interface Recur<T extends Recur<T>> {
    // ...
}

(Обратите внимание на второе упоминание T. Это существенная часть CRTP.)

Также, так определено java.util.Enum, так что тип перечисления под названием Foo должен происходить из Enum, так что это также не редкий шаблон на Java.


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

Есть одно различие (я могу придумать) между Recur решением, которое у меня есть, и Recur решением, которое имеет касательные:

public interface Recur<T extends Recur<T>> {
    T foo();
}

class A implements Recur<B> {
    @Override
    public B foo() {
        return new B();
    }
}

class B implements Recur<A> {
    @Override
    public A foo() {
        return new A();
    }
}

С , вышеуказанное не скомпилировалось бы; с , скомпилировалось бы. Но это просто расщепление волос; это не меняет центральную точку касательной, которая заключается в том, что при уже действительной реализации Recur, Вы можете заставить последующие реализации использовать уже действительный тип, а не саму себя. Я по-прежнему говорю, что это чего-то стоит, но это не стоит больше, чем ответ касательной.

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

23
ответ дан 6 December 2019 в 05:48
поделиться

Я не могу подать Простое «Нет» На этом сайте (тело слишком короткое), так вот идет.

нет.

-5
ответ дан 6 December 2019 в 05:48
поделиться

Это не может быть сделано из-за Type Strasure .

Отредактируйте:

Я спустился голосовал, здесь больше объясняется:

public interface Foo<T>;

T . Выше доступно во время выполнения, поэтому его нельзя проверить. Тем не менее, можно пользовательскую аннотацию, которое могло бы принять это.

0
ответ дан 6 December 2019 в 05:48
поделиться

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

public interface Foo<T extends Foo<?> > {
    T someMethod();
}

Сделав это, вы можете быть уверены, что someMethod () вернет объект, реализующий Foo .


РЕДАКТИРОВАТЬ:

Даже с таким определением интерфейса:

public interface Foo<T extends Foo<T > > {
    T someMethod();
}

Вы можете определить класс Bar2

public class Bar2 implements Foo<Bar2 > {
    @Override
    public Bar2 someMethod() {
        return new Bar2();
    }
}

А затем вы можете определить класс Bar , который реализует Foo , но не возвращает Bar , но Bar2 :

public class Bar implements Foo<Bar2 > {
    @Override
    public Bar2 someMethod() {
        return new Bar2();
    }
}

Первоначальный вопрос заключался в том, можете ли вы подготовиться к использованию такого интерфейса, как Bar сделал.

И ответ: Нет.


РЕДАКТИРОВАТЬ:

Анжелика Лангер дает хорошее объяснение Как мне расшифровать «Enum >»?

14
ответ дан 6 December 2019 в 05:48
поделиться
Другие вопросы по тегам:

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