Массив абстрактного класса. Как получить переменную из дочернего
Создан класс списка из абстрактного класса:
public class List {
protected ArrayList <Transport> transports = new ArrayList();
}
Абстрактный класс:
public abstract class Transport {
protected String model;
protected int price;
protected int maxSpeed;
}
В списке я могу обращаться к переменным абстрактного класса:
for (Transport transport: transports) {
if(transport.price < 30000) {
transport.print();
}
}
Имеется дочерний класс, порождённый от абстрактного, со своими переменными:
public class Car extends Transport {
protected static String type = "Машина";
protected int fuel;
protected int fuel100km;
}
Так вот вопрос, можно ли как-то обращаться из класса списка к переменным дочернего класса?
Ответы (1 шт):
Автор решения: Alex Rudenko
→ Ссылка
- Название класса
Listявно не слишком удачное, так как оно совпадает с названием интерфейсаListиз пакетаjava.util, что может привести к путанице/недоразумениям. - Сама по себе проблема обращения из класса-предка непосредственно к полям классов-потомков -- признак дурно пахнущего кода (code smell), так как класс предок не должен зависеть от свойств / методов, определённых в классах-потомках.
Корректный способ решения: определить в базовом классе некий абстрактный/виртуальный метод, который следует переопределить в потомках в зависимости от их реализации, и использовать необходимые поля потомка в таком методе/методах.
public abstract class Transport {
protected abstract boolean isOk();
public void foo() {
for (Transport transport: transports) {
if (transport.price < 30000 && transport.isOk()) {
transport.print();
}
}
}
public void print() {
// печатать поля класса-предка
}
}
public class Car extends Transport {
@Override
protected boolean isOk() {
return this.fuel > 10;
}
@Override
public void print() {
super.print(); // напечатать поля класса-предка
// напечатать поля данного класса-потомка
}
}
НЕКОРРЕКТНЫЙ способ: проверять конкретный тип класса и приводить к типу класса-потомка для вызова его методов / полей.
public class Transport {
public void foo() {
for (Transport transport: transports) {
if (transport.price < 30000) {
// так НЕ НАДО делать
if (transport instanceof Car) {
Car car = (Car) transport;
car.fuel += 100500;
}
}
}
}
}