Что может означать это объявление общего класса? - PullRequest
8 голосов
/ 24 сентября 2011

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

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

У меня очень ограниченное понимание общего программирования, но я понимаю, что «T» - это Type, а «extends» здесь означает, что Type должен был унаследовать «SimpleGenericClass», но я не понимаю «?» в конце и при каких обстоятельствах этот класс может быть потенциально использован для

public abstract class SimpleGenericClass<T extends SimpleGenericClass<?>> {

}

Ответы [ 5 ]

4 голосов
/ 24 сентября 2011

Во-первых, поскольку класс SimpleGenericClass является абстрактным , он должен быть разделен на подклассы.

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

public abstract class SimpleGenericClass<T...> {
    T x;
}

Теперь first Интересно, что T is ограниченная .Поскольку он объявлен как T extends SimpleGenericClass<?>, это может быть только SimpleGenericClass<?> или некоторый подкласс SimpleGenericClass<?>.Вы также спросили о THR ?.Это известно как подстановочный знак, и есть довольно хорошее объяснение этого в Учебник Java по подстановочным знакам .В вашем случае мы бы сказали, что это «SimpleGenericClass of unknown».Это необходимо в Java, потому что, например, SimpleGenericClass<Object> НЕ является суперклассом SimpleGenericClass<String>.

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

ОБНОВЛЕНИЕ Этот ТАК вопрос о самоограниченных дженериках может быть вам полезен.

ОБНОВЛЕНИЕ 2

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

public abstract class Node<T extends Node<?>> {
    public abstract T[] getChildren();
}

class NumberNode extends Node {
    int data;
    public Node[] getChildren() {return new Node[]{};}
}

class IdentifierNode extends Node {
    int data;
    public Node[] getChildren() {return new Node[]{};}
}

class PlusNode extends Node {
    NumberNode left;
    NumberNode right;
    public NumberNode[] getChildren() {return new NumberNode[]{};}
}

Приятно то, что NumberNode[] является допустимым типом возвратаза PlusNode.getChildren!Имеет ли это значение на практике?Понятия не имею, но это довольно круто.:)

Это не самый лучший пример, но вопрос был довольно открытым («для чего может быть использована такая вещь?»).Конечно, есть и другие способы определения деревьев.

0 голосов
/ 24 сентября 2011

Я думаю, у вас есть вопрос в этой форме (T вместо ?):

public abstract class SimpleGenericClass<T extends SimpleGenericClass<T>>

Посмотрите на этот код:

abstract class Foo<SubClassOfFoo extends Foo<SubClassOfFoo>>
{
    /** subclasses are forced to return themselves from this method */
    public abstract SubClassOfFoo subclassAwareDeepCopy();
}

class Bar extends Foo<Bar> {
    public Bar subclassAwareDeepCopy() {
        Bar b = new Bar();
        // ...
        return b;
    }
}

Bar b = new Bar();
Foo<Bar> f = b;
Bar b2 = b.subclassAwareDeepCopy();
Bar b3 = f.subclassAwareDeepCopy(); // no need to cast, return type is Bar

Трюк с Foo<SubClassOfFoo extends Foo<SubClassOfFoo>>:

  • Любой подкласс Foo должен предоставить аргумент типа для Foo.
  • Этот аргумент типа на самом деле должен быть подклассом Foo.
  • Подклассы Foo (например, Bar) следуют идиоме, что тип аргумент, который они предоставляют Foo, - это они сами.

  • У Foo есть метод, который возвращает SubClassOfFoo. комбинированный с учетом вышеизложенного, это позволяет Foo сформулировать контракт, который говорит «любой мой подкласс должен реализовать subclassAwareDeepCopy() и они должны объявить, что он возвращает этот фактический подкласс «.

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

Трюк сделан, например, в Enum JDK class:

public abstract class Enum<E extends Enum<E>>

Подробнее см. .

0 голосов
/ 24 сентября 2011

Это в основном говорит: в этом классе у вас есть заполнитель типа с именем T и ограничение на этот заполнитель, он должен иметь тип SimpleGenericClass или что-то, что расширяет его.Как только вы подчиняетесь этому правилу, вы можете создавать экземпляры вашего класса и присваивать фактический тип T, который впоследствии можно будет использовать в методах этого класса, что-то вроде этого:

public class C <T extends Number>{

    public void doSomething(T t) {

    }

    public static void main(String... args) {
        //works:
        C<Number> c = new C<Number>();
        c.doSomething(new Number() {
            //Aonimous implementation of number

        });

        //won't work
        //C<Object> c = new C<Object>();

        C<Integer> c2 = new C<Integer>();       
        c2.doSomething(new Integer(1));
        //won't work
        //c2.doSomething(new Number() {

            //Aonimous implementation of number
        //});
    }
}

SimpleGenericClass<?>довольно избыточно на данный момент.Если для этого класса требуется другой универсальный тип, у вас может быть более одного (SimpleGenericClass<T extends SimpleGenericClass, T2 extends Whatever>)

0 голосов
/ 24 сентября 2011

По определению говорится, что SimpleGenericClass может работать с типом <T>, который является подклассом SimpleGenericClass.

Так что я предполагаю, что будут некоторые операции, которые будут работать на <T>.

Теперь, чтобы понять, почему можно определить такой шаблон - (на самом деле, я не очень много думаю) может быть сценарий, в котором SimpleGenericClass является абстрактным классом ( только что понял, что он соответствует OP: P ) и ожидает, что он может работать на каких-то конкретных классах?

Ребята, что вы думаете?

0 голосов
/ 24 сентября 2011

Это на самом деле означает только то, что вы разрешаете пользователю класса SimpleGenericClass параметризовать экземпляры класса с типом T. Однако T не может быть любого типа, но должен быть подтипом SampleGenericClass (или самого SampleGenericClass).

В оставшейся части кода класса SimpleGenericClass вы можете использовать тип T в сигнатурах методов.

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

new SimpleGenericClass<SampleGenericClass<String>>();

Т.е. вы параметризуете SimpleGenericClass с помощью SampleGenericClass и SampleGenericClass с помощью String.

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