Wie überschriebenen Methoden in einer Unterklasse nennen? Potenzielle Kandidaten für Refactoring
-
12-09-2019 - |
Frage
Ursprünglich hatte ich ein Design Problem, wo ich fünf Unterklassen von einer übergeordneten Klasse benötigt, wo alle bis auf zwei die gleiche generische Methode, Dinge zu tun und die andere beiden Klassen müßten spezielle Handhabung verwenden würden. Ich wollte das Verfahren fünf Mal zu vermeiden, zu schreiben; zwei Sonderfälle und drei identische.
So ich jede Klasse hatte erben Oberklasse, und sein doSomething () -Methode und hatte SubClassSpecial1 und SubClassSpecial2 Überschreibung mit ihrer eigenen Methode DoSomething.
Das war alles in Ordnung, bis ich eine Methode, die etwas sah schrieb wie
void fooBar(SuperClass obj) {
obj.doSomething()
}
, und es könnte als fooBar( new SubClassSpecial1() );
aufgerufen werden
Das Problem ist, dass die Laufzeitklasse der obj
Variable nun, dass die übergeordneten Klasse ist, und so wird es die Methoden in der übergeordneten Klasse definiert nennen. Ich könnte natürlich, einen abstrakten doSometing () -Methode in der übergeordneten Klasse machen, und jede Unterklasse ihre eigene Version machen implementieren, aber das wäre Code in drei der Klassen duplizieren. Und ich möchte zu vermeiden, das zu tun ...
Ich würde jeder Gewinn Polymorphismus verlieren gibt, wenn ich eine Menge Verzweigung durch
hatteif(obj.getClass().getName() == "SubClassSpecial1" ) ((SubClassSpecial1) obj).doSomething()K;
else if ...
Also, was soll ich tun, um das Design elegante und un-hackish zu machen?
Lösung
Was haben Sie sollten in Ordnung beschrieben arbeiten, wie ist.
Ist obj.doSomething () tatsächlich die Umsetzung Super nennen? Wenn ja, sind zwingende Sie es nicht richtig. Überprüfen Sie, ob Sie nicht die Unterschrift in Ihre überschriebene Versionen geändert.
Andere Tipps
Ich bin ein bisschen von diesem Teil Ihrer Frage verwirrt:
Natürlich, was ich tun wollte, war haben jedes Objekt seine eigene Version von doSomething () aufrufen, aber nicht erkennen, dass, um das zu tun, benötigt obj als einer der Unterklassen Methoden deklariert werden. Und jetzt ist es ein Chaos.
Natürlich steht die Deklaration spielt keine Rolle, die doSomething () -Methode wird immer nach dem Laufzeittyp der Klasse aufgerufen werden.
Also ich denke, was Sie versuchen, einfach gut zu tun sollte funktionieren, z.B. diese Erklärungen können alle auf die foobar Methode zu übergeben verwendet werden:
SuperClass sc1 = new SubClassSpecial1();
SubClassSpecial2 sc2 = new SubClassSpecial2();
//etc..
Wenn Sie diese:
void fooBar(SuperClass obj) {
obj.doSomething();
}
dann die Compiler- Art von obj
ist SuperClass
. Dies bedeutet, dass der Compiler, dass SuperClass
überprüfen wird hat eine doSomething()
Methode.
Bei Laufzeit Sie eine Unterklasse von SuperClass
ersetzen kann, ist dies die Liskov Substitutionsprinzip . Verfahren foobar()
weiß nicht, und soll nicht wissen, was der Laufzeittyp von obj
ist, nur, dass es aus SuperClass
ableitet und so kann doSomething()
aufgerufen werden.
Wie zu Ihrem Beispiel:
fooBar( new SubClassSpecial1() );
In diesem Fall, dass Sie wissen, passieren, dass die Laufzeit Typ des Parameters SubClassSpecial1
ist die doSomething()
speziell außer Kraft setzt. In allen Fällen ist die richtige Methode aufgerufen wird.
Ein Wort über Refactoring. Möglicherweise möchten Sie Refactoring Ihrer Hierarchie betrachten.
Ihre Basisklasse SuperClass
sollte doSomething()
als abstrakt definieren. Ihre drei Klassen, die die gleiche Umsetzung doSomething()
benötigen, sollten sie von einer Zwischenbasisklasse erben, die diese spezifische Implementierung hat. Ihre zwei speziellen Klassen sollten direkt von SuperClass
erben und haben ihre eigene Implementierung von doSomething()
.