«Переопределение» переменных экземпляра в подтипе: возможные риски? - PullRequest
1 голос
/ 19 мая 2010

Скажем, у меня был класс SuperClass и два подкласса SubClassA и SubClassB, которые наследуются от SuperClass.

 abstract class SuperClass{
   ...
   List someList;
   ...
 }

 class SubClassA extends SuperClass{
   ...
   List<String> someList;
   ...
 }

 class SubClassB extends SuperClass{
   ...
   List<Integer> someList;
   ...
 }

Таким образом, это удобно, потому что я могу получить someList.size() в Superclass и иметь безопасность типов в подклассах. Проблема в том, что он не «чувствует» себя хорошо, можете ли вы подумать о потенциальных опасностях этого apporach, о которых я не знаю?

Ответы [ 4 ]

8 голосов
/ 19 мая 2010

С одной стороны, любой метод SuperClass видит список суперклассов, а не список подклассов. Это почти наверняка приводит к тонким ошибкам. Например. когда вы говорите

Я могу получить someList.size() в Superclass

На самом деле вы получаете размер списка в Superclass, а не подкласс. Список суперклассов может быть пустым, в то время как список подклассов содержит элементы (или наоборот).

Причина этого в том, что SubClassA.someList никоим образом не заменяет и не переопределяет Superclass.someList - он просто затеняет его, поэтому методы подкласса видят SubClassA.someList вместо Superclass.someList. Однако это абсолютно не влияет на Superclass. Методы можно сделать виртуальными (а в Java они по умолчанию), но члены данных не могут.

1 голос
/ 19 мая 2010

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

Замените переменную на метод, который я предлагаю.

спасибо.

1 голос
/ 19 мая 2010

Мне кажется, что нарушают IS-A и принцип замещения Лискова. Если у вас есть коллекция экземпляров SuperClass, каждый из которых может быть SubClassA или SubClassB, вы получите в лучшем случае неожиданное поведение.

Не делай этого.

Может быть, лучше использовать дженерики:

public class X<T>
{
    private List<T> list;
}
1 голос
/ 19 мая 2010

Это действительно плохая идея. Вы действительно хотите, чтобы экземпляр любого подкласса имел два списка? Потому что это то, что происходит. Вы объявляете вторую переменную - поэтому код в суперклассе будет использовать одну переменную, а код в подклассе будет использовать другую. Это просто напрашивается на неприятности, ИМО.

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