2010-05-19 2 views
1

Скажем, у меня был класс 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, о котором я не знаю?

ответ

8

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

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

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

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

+0

Они могут быть разными ссылками, указывающими на один и тот же объект. (Хотя 'private' и' final' помогли бы как всегда.) –

+0

@ Тома, хорошая точка, не подумал об этом ... возможно, потому что, хотя семантически правильно, это все равно было бы уродливым, излишне сложным, понять решение (для меня). –

+0

Я нашел трудный путь, что он фактически затеняет. Единственное, что я сделал здесь, это по существу трюк компилятора (и меня). – sebastiangeiger

1

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

1

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

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

Может что-то с помощью дженериков было бы лучше:

public class X<T> 
{ 
    private List<T> list; 
} 
1

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

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

спасибо.

Смежные вопросы