«Переопределение» переменных экземпляров в подтипе: возможные риски?
-
30-09-2019 - |
Вопрос
Скажем, у меня был класс суперкласса и два подкласса подклассы и подклассб, наследующий от суперкласса.
abstract class SuperClass{
...
List someList;
...
}
class SubClassA extends SuperClass{
...
List<String> someList;
...
}
class SubClassB extends SuperClass{
...
List<Integer> someList;
...
}
Таким образом, это удобно, потому что я могу получить someList.size()
в Superclass
и имеют набережные в подклассах. Проблема в том, что она не «чувствует» правильно, вы можете подумать о потенциальных опасностях этого Apporach, есть ли я не знаю?
Решение
На одну вещь, любой метод SuperClass
Видит список суперкласса, а не в подклассе. Это почти наверняка приводит к тонким ошибкам. Например, когда вы говорите
я могу получить
someList.size()
вSuperclass
То, что вы на самом деле получаете, это размер списка в Superclass
, не то, что из подкласса. Список SuperClass может быть пустым, пока список подкласса содержит элементы (или наоборот).
Причина этого в том, что SubClassA.someList
никоим образом не заменяет или не переопределяет Superclass.someList
- это просто тени, поэтому методы подкласса видят SubClassA.someList
вместо Superclass.someList
. Отказ Однако это абсолютно не влияет на Superclass
. Отказ Методы могут быть сделаны виртуальными (и в Java, они по умолчанию), но члены данных не могут.
Другие советы
Это действительно плохое представление. Ты В самом деле хочу экземпляр любого подкласса, чтобы иметь два списки? Потому что это происходит. Вы объявляете вторую переменную - поэтому код в SuperClass будет использовать одну переменную, а код в подклассе будет использовать другой. Это просто просит неприятностей, ИМО.
Я думаю, что вы предпочитаете определить метод вместо переменной элемента класса. Так что вы сможете реализовать методы в ваших подкладках и не нужно беспокоиться о безопасности типа.
Замените переменную методом, который я предлагаю.
Благодарю.
Кажется, сломается - А и принцип замены ликов для меня. Если у вас есть коллекция экземпляров SuperClass, каждый из которых может быть подкласса или подкласса, вы получите некоторое удивительное поведение в лучшем случае.
Не делай этого.
Может быть, что-то использование дженериков было бы лучше:
public class X<T>
{
private List<T> list;
}