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

hatte
if(obj.getClass().getName() == "SubClassSpecial1" )  ((SubClassSpecial1) obj).doSomething()K;
else if ...

Also, was soll ich tun, um das Design elegante und un-hackish zu machen?

War es hilfreich?

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().

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top