5 Stimmen

Wie ruft man überschriebene Methoden in einer Unterklasse auf? Potenzieller Kandidat für ein Refactoring

Ursprünglich hatte ich ein Design-Problem, bei dem ich fünf Unterklassen einer Oberklasse brauchte, von denen alle bis auf zwei dieselbe generische Methode verwenden würden, während die anderen beiden Klassen eine spezielle Behandlung benötigen würden. Ich wollte vermeiden, die Methode fünfmal zu schreiben: zwei Sonderfälle und drei identische Fälle.

So hatte ich jede Klasse erben SuperClass, und seine doSomething() Methode, und hatte SubClassSpecial1 und SubClassSpecial2 überschreiben mit ihren eigenen doSomeThing Methode.

Das war alles in Ordnung, bis ich eine Methode schrieb, die in etwa so aussah

void fooBar(SuperClass obj) {
    obj.doSomething()
}

und es könnte aufgerufen werden als fooBar( new SubClassSpecial1() );

Das Problem ist, dass die Laufzeitklasse des obj Variable ist nun die der Oberklasse und ruft daher die in der Oberklasse definierten Methoden auf. Ich könnte natürlich eine abstrakte doSometing()-Methode in der Oberklasse erstellen und jede Unterklasse ihre eigene Version implementieren lassen, aber das würde den Code in drei der Klassen duplizieren. Und das möchte ich vermeiden ...

Ich würde alle Vorteile der Polymorphie verlieren, wenn ich eine Menge Verzweigungen durch

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

Was sollte ich also tun, um das Design eleganter und nicht hakelig zu gestalten?

5voto

NickDK Punkte 4939

Dieser Teil Ihrer Frage verwirrt mich ein wenig:

Natürlich wollte ich, dass jedes Objekt seine eigene Version von doSomething() aufruft, aber ich habe nicht bemerkt, dass obj als eine der untergeordneten Methoden deklariert werden muss, um das zu tun. Und jetzt ist es ein Durcheinander.

Natürlich spielt die Deklaration keine Rolle, die doSomething()-Methode wird immer entsprechend dem Laufzeittyp der Klasse aufgerufen.

Ich denke also, dass das, was Sie zu tun versuchten, gut funktionieren sollte, z. B. können diese Deklarationen alle verwendet werden, um an die foobar-Methode zu übergeben:

SuperClass sc1 = new SubClassSpecial1();
SubClassSpecial2 sc2 = new SubClassSpecial2();
//etc..

2voto

Terry Wilcox Punkte 9000

Das, was Sie beschrieben haben, sollte auch so funktionieren.

Ruft obj.doSomething() tatsächlich die Implementierung der Oberklasse auf? Wenn ja, haben Sie sie nicht richtig überschrieben. Überprüfen Sie, dass Sie die Signatur in Ihren überschriebenen Versionen nicht geändert haben.

1voto

quamrana Punkte 32950

Wenn Sie das haben:

void fooBar(SuperClass obj) {
    obj.doSomething();
}

dann die Kompilierzeit Art der obj es SuperClass . Dies bedeutet, dass der Compiler prüft, ob SuperClass hat eine doSomething() Methode.
Unter Laufzeit können Sie durch eine Unterklasse von SuperClass ist dies die _Liskov-Substitutionsprinzip_ . Methode foobar() weiß nicht und sollte auch nicht wissen, was der Laufzeittyp von obj ist, sondern nur, dass sie sich von SuperClass y así doSomething() aufgerufen werden kann.

Was Ihr Beispiel anbelangt:

fooBar( new SubClassSpecial1() );

In diesem Fall wissen Sie zufällig, dass die Laufzeit Der Typ des Parameters ist SubClassSpecial1 die ausdrücklich übergeordnet ist doSomething() . In allen Fällen wird die richtige Methode aufgerufen.

Ein Wort zum Refactoring. Sie sollten eine Umstrukturierung Ihrer Hierarchie in Betracht ziehen.
Ihre Basisklasse SuperClass sollte definieren doSomething() als Zusammenfassung. Ihre drei Klassen, die die gleiche Implementierung von doSomething() von einer dazwischenliegenden Basisklasse erben, die über diese spezifische Implementierung verfügt. Ihre beiden speziellen Klassen sollten direkt von folgenden Klassen erben SuperClass und haben ihre eigene Implementierung von doSomething() .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X