2017-01-19 2 views
0

Ich habe zwei Klassen, A und B, wo B erweitert A. Ich habe ein Problem, wo B ein zusätzliches Feature, das mit einer Ausnahme ExceptionC kommt, die nicht in irgendeiner Form oder Form zu A, aber es wird nicht kompiliert, es sei denn A spezifiziert, dass es throws ExceptionC ist. Ich verstehe, dass dies beabsichtigt ist (wegen des Liskow-Substitutionsprinzips). Meine Frage ist zweifach:Overriding-Methode mit geprüften Ausnahmen

  1. Was ist der Grund für das Liskov Substitutionsprinzip? Wenn B A erweitert, kann es dann nicht weitere Features und damit Ausnahmen hinzufügen?
  2. Was wäre ein besserer Weg, dies zu tun? Es fühlt sich falsch an, der Oberklasse eine nicht anwendbare Ausnahme hinzuzufügen.

Spezifische Situation:

Ich bin eine Implementierung ultimative Tic-Tac-Toe in Java zu schreiben. Grundsätzlich nehmen ein Tic-Tac-Toe-Raster und füllen es mit Tic-Tac-Toe-Gitter, wie folgt aus:

| | # | | # | | 
| | # | | # | | 
| | # | | # | | 
################# 
| | # | | # | | 
| | # | | # | | 
| | # | | # | | 
################# 
| | # | | # | | 
| | # | | # | | 
| | # | | # | | 

Sie in der Mitte beginnen und wo X in diesem Gitter geht, geht O im Raster entspricht mit dem auf dem größeren, so dass nach zwei Zügen es könnte wie folgt aussehen:.

| |O# | | # | | 
| | # | | # | | 
| | # | | # | | 
################# 
| | #X| | # | | 
| | # | | # | | 
| | # | | # | | 
################# 
| | # | | # | | 
| | # | | # | | 
| | # | | # | | 

und wenn das Zielgitter voll ist oder bereits gewonnen wurde, kann die nächste Person wählen, in welchem ​​Netz zu gehen

Ich habe zwei normale Klassen, zwei Ausnahmeklassen und eine Schnittstelle.

  • TTTBoard implementiert Vorstand
  • UltimateTTTBoard erweitert TTTBoard Vorstand implementiert
  • TTTBoard.move wirft LocationTakenException
  • UltimateTTTBoard.move wirft LocationTakenException, TargetBoardFullException

Beachten Sie, dass in Standard-Tic-Tac-Toe Da es nur eine Karte gibt, ist TargetBoardFullException vollständig nicht anwendbar.

Mache ich das falsch? Sollte ich Ausnahmen dafür nicht verwenden?

+0

Der Grund für LSB ist das Wort * substitution *, also wenn B einiges ganz anders macht und mehr Code benötigt, um damit zu arbeiten (wie ein 'try/catch' Block), dann kann man nicht ersetzen/ersetze das mit "C" ohne weitere Refactorings. So kann "B" Dinge anders machen, aber sollte nicht Regeln brechen, die durch "A" definiert sind. – Tom

+0

B sollte ExceptionC abfangen und es in eine Art von Ausnahme umwandeln, die A werfen darf, vielleicht indem es es umhüllt. Oder besser noch, B's Ausnahmen könnten Unterklassen von A's Ausnahmen sein. –

+0

Hmm. Vielleicht wäre es leichter zu verstehen, wenn ich die genaue Situation angeben würde. Ich werde die Frage jetzt aktualisieren. –

Antwort

1

Der folgende Code zeigt, warum Java nicht erlaubt, den Vertrag zu ändern:

class A { 
    public void method() { 
     // do something 
    } 
} 

class B extends A { 
    public void method() throws IOException { // <- compile error here 
     // do something and throw and exception 
    } 
} 

class App { 
    public static void main(String[] args) { 
     A a = new B(); 
     a.method(); // to try or not to try, that's the question now. 
    } 
} 

Natürlich ist es nicht kompilieren lässt. Aber wenn es so wäre, müssten wir eine IOException in der Hauptmethode abfangen (weil es eine B Instanz ist) oder nicht (weil wir die Methode auf der Schnittstelle aufrufen)?

+0

* "auf der Schnittstelle" * 'A' ist jedoch keine Schnittstelle. – Tom

+0

Ich verstehe, was der Code macht. Ich habe nur Schwierigkeiten zu begreifen, warum du A a = new B() machen willst. –

+0

Und was soll ich stattdessen tun? Ich habe die Frage unter bestimmten Umständen aktualisiert. –