“Prioritario” variabili di istanza in sottotipo: Possibili rischi?
-
30-09-2019 - |
Domanda
dire che ho avuto una classe SuperClass e due sottoclassi SubClassA e SubClassB che ereditano da superclasse.
abstract class SuperClass{
...
List someList;
...
}
class SubClassA extends SuperClass{
...
List<String> someList;
...
}
class SubClassB extends SuperClass{
...
List<Integer> someList;
...
}
In questo modo è conveniente perché posso ottenere someList.size()
in Superclass
ed avere sicurezza rispetto ai tipi nelle sottoclassi.
Il problema è che non "sentire" a destra, si può pensare a potenziali pericoli questa suddetto approccio ha che io non sono a conoscenza?
Soluzione
Per prima cosa, qualsiasi metodo di SuperClass
vede la lista superclasse, non quello della sottoclasse. Questo porta quasi sicuramente a bug sottili. Per esempio. quando si dice
posso ottenere
someList.size()
inSuperclass
quello che in realtà è la dimensione della lista in Superclass
, non quello della sottoclasse. L'elenco superclasse può essere vuota mentre la lista sottoclasse contiene elementi (o viceversa).
La ragione di questo è che SubClassA.someList
non sostituisce in alcun modo o sostituzione Superclass.someList
- solo ombre, così i metodi delle sottoclassi vedono SubClassA.someList
invece di Superclass.someList
. Tuttavia, questo non ha assolutamente alcun effetto in Superclass
. I metodi possono essere fatte virtuale (e in Java, che sono di default), ma i membri dati non possono.
Altri suggerimenti
Questa è una pessima idea. Ti davvero desidera un'istanza di una sottoclasse di avere due liste? Perché questo è ciò che sta accadendo. Si sta dichiarando una seconda variabile - così il codice nella superclasse utilizzerà una variabile, e il codice nella sottoclasse utilizzerà un'altra. Questo è solo in cerca di guai, IMO.
Credo che si dovrebbe piuttosto definire un metodo al posto della variabile membro della classe. In modo che si sarà in grado di implementare i metodi nelle classi secondarie e non c'è bisogno di preoccuparsi per la sicurezza tipo.
Sostituire variabile con metodo che suggerisco.
Grazie.
sembra rompere IS-A e il principio di sostituzione Liskov a me. Se si dispone di una collezione di istanze superclasse, ognuno dei quali può essere SubClassA o SubClassB, avrai un comportamento sorprendente al meglio.
Non farlo.
Forse qualcosa usando farmaci generici sarebbe meglio:
public class X<T>
{
private List<T> list;
}