Bewährte Methode zum Implementieren einer abgeleiteten Methode, die nicht aufgerufen werden sollte [closed]

8

Ich habe eine JAVA-Klasse A, die eine Methode foo

hat %Vor%

Ich habe auch eine abgeleitete Klasse von A - MutableA. MutableA ist ein Singleton-Objekt, das angibt, dass keine Aktualisierung erforderlich ist, die für die Wiederverwendung von Code-Flows nützlich ist. foo () sollte nie auf MutableA aufgerufen werden. Was ist der beste Weg, um das zu erreichen:

  1. Wirf Unsupported exception
  2. Nichts tun (leere Implementierung)
  3. Das ist ein schlechtes Design was auch immer.

Kann mir jemand empfehlen, was in diesem Fall die beste Vorgehensweise ist?

    
user844541 16.02.2015, 09:51
quelle

6 Antworten

2

Ich würde überdenken, das Design zu überdenken.

Wenn eine abstrakte Methode in der Superklasse verwendet wird, bedeutet dies, dass Unterklassen diese Methode implementieren sollten. Sofern Sie keine größere Hierarchie planen, sollten Sie in Erwägung ziehen, die foo-Methode in der Hierarchie näher an die Implementierung zu verschieben.

Wenn Sie beabsichtigen, den Standort der foo-Methode beizubehalten, würde ich auch MutableA abstrakt machen.

    
Rickard Nilsson 16.02.2015 10:01
quelle
2

Sie sollten sich das Liskov-Substitutionsprinzip ansehen, das eines der grundlegenden SOLID-Prinzipien für gutes Design ist.

Das Prinzip besagt, dass sich abgeleitete Objekte nicht anders verhalten sollten als ihre Eltern. Ein gängiges Beispiel für eine Verletzung des Liskov-Prinzips ist die Ableitung eines Kreises aus einer Ellipse. Was mathematisch völlig sinnvoll ist und Klang als schlechtes Design gilt, denn ein aus einer Ellipse abgeleiteter Kreis würde (zum Beispiel) immer noch die Methoden zur Einstellung der Breite und Höhe offenlegen, würde sich aber in manchen Kontexten merkwürdig verhalten. Berücksichtigen Sie Folgendes:

%Vor%

Wenn wir nicht wissen, dass ein Aufrufer einen Kreis statt einer Ellipse passiert hat und wir sowohl die Breite als auch die Höhe festgelegt haben, können unsere Ergebnisse von unseren Erwartungen abweichen, da der Kreis entweder SetHeight ignoriert oder den Breiten-Bot auf SetWidth setzt und SetHeight. Wie auch immer, dieses Verhalten ist unerwartet, wenn wir erwarten, auf einer Ellipse zu operieren. Daher das Liskov-Substitutionsprinzip.

    
Paul Kertscher 16.02.2015 11:04
quelle
2

Da Sie "no update is needed not necessary" sagen, scheint es, als wäre eine leere Implementierung der richtige Weg. Was mache ich:

%Vor%

Ich würde nicht wissen, ob ich ein MutableA zurückbekommen habe oder nicht, also rufe ich foo an, nur um sicher zu gehen.

Wenn verboten ist foo auf einem MutableA aufzurufen, würde ich mit UnsupportedOperationException gehen oder das Design überdenken. Vielleicht könnten Sie A in eine AHandler umbrechen, die weiß, wann und wie foo für die umbrochene Instanz aufgerufen wird.

    
aioobe 16.02.2015 09:58
quelle
1

Es kommt darauf an, für welche Methode die Methode gedacht ist. Alle Alternativen, die Sie aufgelistet haben, sind praktisch gut.

Übrigens, wenn Sie eine UnsupportedOperation Ausnahme auslösen, sagen Sie, dass diese Methode nicht verwendet werden soll. Das Verwenden einer Ausnahme ist immer eine "Nachricht" einer Abweichung von der "normalen", also definieren Sie etwas mit der Basisimplementierung von A.foo() , aber Sie brechen diese Implementierung auch mit der Unterklasse auf.

Wenn Sie eine leere Implementierung verwenden, machen Sie die Unterklasse innerhalb eines hypothetischen Flusses brauchbarer, ohne mit der Vergangenheit aufzubrechen (die Superklasse A ), so dass Sie in keinem Kontext über die Verwendung von Unterklassen Bescheid wissen will.

In der abschließenden Analyse haben Sie gesagt, dass MutableA Singleton ist, also denke ich, dass Sie es in einem bestimmten Kontext mit einem bestimmten Blick darauf verwenden werden: Ich würde also die "Ausnahme" -Lösung übernehmen.

    
cigno5.5 16.02.2015 10:05
quelle
1

Ich würde so etwas verwenden:

%Vor%

Überall in Ihrem Code, wo Sie A erhalten möchten, verwenden Sie stattdessen ReadableA , es sei denn, Sie möchten ausdrücklich foo() aufrufen. Fügen Sie dann A in Ihre Methodensignatur ein. Wenn Sie eine MutableA erhalten möchten, schreiben Sie eine MutableA Signatur.

Beispiele:

%Vor%     
Olivier Grégoire 16.02.2015 10:12
quelle
1

Ich denke, dass das Werfen von UnsupportedOperationException hier die richtige Wahl ist. Angenommen, Sie erweitern die Klasse A um 3 Klassen.

%Vor%

Nun sollte sich X,Y,Z and MutableA in einer Design-Perspektive in einer konsistenten Weise verhalten, in Bezug auf foo() . Ich würde es abraten, eine andere Klassenhierarchie einzuführen, um MutableA fofree zu machen. Eine einfache Lösung wäre ein UnsupportedOperationException und der Aufrufer würde wissen, dass die Methode nicht vom aufrufenden Objekt unterstützt werden kann. Eine leere Implementierung andererseits ist immer noch gültig und passt ehrlich gesagt nicht gut in Design-Perspektive , weil sie noch ist ein gültiger Aufruf vom aufrufenden Objekt .

PS: Ich würde auch das Umdenken des Designs in Erwägung ziehen. Jede Methode, die verfügbar ist, aber nicht verwendet werden sollte, ist nicht Teil eines guten Designs.

    
TheLostMind 16.02.2015 10:24
quelle