Логика обобщенных классов

Рейтинг: 0Ответов: 1Опубликовано: 05.02.2023

Читаю документацию: про обобщеные классы вот код:

class Account<T>
{
    private T _id;
    T getId(){return _id;}
    Account(T id)
    {
        _id = id;
    }
}
 
class DepositAccount extends Account<Integer>{
 
    DepositAccount(){
        super(5);
    }
}

при наследовании класса Account, который имеет параметр T при наследовании мы указали класс(параметр) Integer

А как будет оно работать на наследие и возможно ли наследовать обобщенные классы без параметров?

Ответы

▲ 1Принят

Наследование обобщённых классов может выполняться следующими способами

  • Потомок -- обобщённый класс:
class GenParent<T> {
    T foo;
}
class GenChild<E> extends GenParent<E> {}

Класс-потомок предоставляет некий дополнительный обобщённый функционал, как и его предок. То есть у класса GenChild указан (несвязанный unbounded) аргумент типа, и компилятор знает, что при использовании такого класса необходимо указать конкретный тип.

  • Потомок -- конкретный класс
class IntChild extends GenParent<Integer> {}

Класс-потомок использует конкретный тип Integer, наследуя обобщённый класс. Здесь поле foo (а также соответствующие геттеры/сеттеры/аргументы конструктора и т.д.) приобретает конкретный тип Integer, известный компилятору.

  • Потомок -- "сырой" (raw) класс
class RawChild extends GenParent {}

Не рекомендуемый способ, так как компилятор знает GenParent -- обобщённый класс и не может найти требуемый конкретный тип, потому выдаёт предупреждение вида:

GenParent is a raw type. References to generic type GenParent should be parameterized

В данном случае такое объявление эквивалентно class RawChild extends GenParent<Object>, о чем указано в комментарии Дмитрия, поле foo становится типа Object, и может принимать объекты любого типа, что характерно для типонебезопасного кодирования начала 2000-х годов до появления Java 1.5.