Обобщенные классы могут участвовать в иерархии наследования: могут наследоваться от других, либо выполнять роль базовых классов. Рассмотрим различные ситуации.
При наследовании от обобщенного класса класс-наследник должен передавать данные о типе в конструкции базового класса:
class Account<T>
{
private T _id;
T getId(){return _id;}
Account(T id)
{
_id = id;
}
}
class DepositAccount<T> extends Account<T>{
DepositAccount(T id){
super(id);
}
}
В конструкторе DepositAccount идет обращение к конструктору базового класса, в который передаются данные о типе.
Варианты использования классов:
DepositAccount dAccount1 = new DepositAccount(20);
System.out.println(dAccount1.getId());
DepositAccount dAccount2 = new DepositAccount("12345");
System.out.println(dAccount2.getId());
При этом класс-наследник может добавлять и использовать какие-то свои параметры типов:
class Account<T>
{
private T _id;
T getId(){return _id;}
Account(T id)
{
_id = id;
}
}
class DepositAccount<T, S> extends Account<T>{
private S _name;
S getName(){return _name;}
DepositAccount(T id, S name){
super(id);
this._name=name;
}
}
Варианты использования:
DepositAccount<Integer, String> dAccount1 = new DepositAccount(20, "Tom");
System.out.println(dAccount1.getId() + " : " + dAccount1.getName());
DepositAccount<String, Integer> dAccount2 = new DepositAccount("12345", 23456);
System.out.println(dAccount2.getId() + " : " + dAccount2.getName());
И еще одна ситуация - класс-наследник вообще может не быть обобщенным:
class Account<T>
{
private T _id;
T getId(){return _id;}
Account(T id)
{
_id = id;
}
}
class DepositAccount extends Account<Integer>{
DepositAccount(){
super(5);
}
}
Здесь при наследовании явным образом указывается тип, который будет использоваться конструкциями базового класса, то есть тип Integer.
Затем в конструктор базового класса передается значение именно этого типа - в данном случае число 5.
Вариант использования:
DepositAccount dAccount1 = new DepositAccount(); System.out.println(dAccount1.getId());
Также может быть ситуация, когда базовый класс является обычным необобщенным классом. Например:
class Account
{
private String _name;
String getName(){return _name;}
Account(String name)
{
_name=name;
}
}
class DepositAccount<T> extends Account{
private T _id;
T getId(){return _id;}
DepositAccount(String name, T id){
super(name);
_id = id;
}
}
В этом случае использование конструкций базового класса в наследнике происходит как обычно.
Объект одного обобщенного типа можно привести к другому типу, если они используют один и тот же тип. Рассмотрим преобразование типов на примере следующих двух обобщенных классов:
class Account<T>
{
private T _id;
T getId(){return _id;}
Account(T id)
{
_id = id;
}
}
class DepositAccount<T> extends Account<T>{
DepositAccount(T id){
super(id);
}
}
Мы можем привести объект DepositAccount<Integer> к Account<Integer> или DepositAccount<String> к Account<String>:
DepositAccount<Integer> depAccount = new DepositAccount(10); Account<Integer> account = (Account<Integer>)depAccount; System.out.println(account.getId());
Но сделать то же самое с разнотипными объектами мы не можем. Например, следующий код не будет работать:
DepositAccount<Integer> depAccount = new DepositAccount(10); Account<String> account = (Account<String>)depAccount;