Warum sollten Sie sich mit abstrakten oder Interface-Klassen beschäftigen?

8

Das hat mich verblüfft, warum es besser ist, eine abstrakte Klasse zu haben. Also muss ich sagen, dass ich Bereiche mit verschiedenen Formen (Kreis, Rechteck) berechnen muss. Mir wurde beigebracht, es sei besser, eine abstrakte / Interface-Form zu haben und dann Klassen wie Rectangle, Circle, das es erweitert.

Ich habe den folgenden Code erstellt

%Vor%

Es scheint, dass die Formklasse keinen Zweck erfüllt. Ich kann eine getArea-Implementation in der Shape-Klasse nicht durchführen, da verschiedene Formen die Fläche unterschiedlich berechnen. Ich könnte nur die Formklasse entfernen und meinen Code vereinfachen.

Was wäre der eigentliche Zweck einer abstrakten / Interface-Klassenform? Vielen Dank im Voraus für jede Erklärung

    
kype 19.10.2013, 08:01
quelle

4 Antworten

16
  

Es scheint, dass die Formklasse keinen Zweck erfüllt. Ich kann eine getArea-Implementation in der Shape-Klasse nicht durchführen, da verschiedene Formen die Fläche unterschiedlich berechnen. Ich könnte nur die Formklasse entfernen und meinen Code vereinfachen.

Angenommen, Sie haben ein Bild, das aus mehreren Formen besteht - einigen Kreisen, einigen Rechtecken usw. Sie können alle diese Formen in List<Shape> speichern und dann die Gesamtfläche berechnen mit:

%Vor%

Wie würden Sie das tun, wenn Sie keine gemeinsame Shape -Klasse oder Schnittstelle hätten? Ihre Klasse Picture müsste über jede einzelne Formklasse Bescheid wissen, anstatt die Gemeinsamkeit zwischen den verschiedenen Formklassen zu verwenden, um den Code allgemeiner zu gestalten.

Betrachten Sie als weiteres Beispiel Streams. Stellen Sie sich vor, wir hätten nicht die Klasse InputStream - wir hatten nur die einzelnen Unterklassen. Dann müssten Sie jedes Mal, wenn Sie Code schreiben, der einige Daten lesen muss, eine Überladung für jede einzelne Unterklasse bereitstellen, die Sie handhaben möchten, obwohl der Code in jeder Methode genau gleich wäre. InputStream abstrahiert die Unterschiede und stellt die allgemeine Funktionalität (Lesen, Überspringen usw.) zur Verfügung. Auf diese Weise können Sie eine einzelne Methode schreiben, die nur InputStream benötigt, und dann mit einer FileInputStream oder einer ByteArrayInputStream etc ... aufrufen, ohne dass die Methode sich darum kümmern muss, welche sie empfängt.

    
Jon Skeet 19.10.2013, 08:04
quelle
7

Wenn Sie eine beliebige Shape an eine Methode übergeben möchten, können Sie Folgendes tun:

%Vor%

Dies nennt man Polymorphismus. Wenn es keine abstrakte Klasse oder Schnittstelle gibt, können Sie dies nicht tun.

    
Petar Minchev 19.10.2013 08:05
quelle
5

Sie können eine Schnittstelle oder eine abstrakte Klasse verwenden, wenn Sie Klassen basierend auf bestimmten Verhaltensweisen oder Eigenschaften gruppieren möchten. Dadurch können Sie die Schnittstelle / abstrakte Klasse als Parametertypen oder in Generika verwenden. In Ihrem Fall können Sie beispielsweise Folgendes tun:

  1. Erstellen einer Liste mit verschiedenen Formen List <Shape> .
  2. Übergeben Sie eine Form an eine Methode. Nehmen wir an, Sie haben eine Methode getArea() auf Ihrer Shape-Klasse / Schnittstelle. Sie können es dann in einer Methode whichIsGreater (Shape shape1, Shape shape2) verwenden, die getArea() method in ihrer Implementierung verwendet.

Es gibt noch einen weiteren sehr wichtigen Aspekt der Verwendung von Interfaces oder abstrakten Klassen. Wenn Sie für Ihre Klassen eine abstrakte Klasse (oder eine Schnittstelle) definiert haben, wird die Absicht Ihres Codeentwurfs angezeigt. Jemand, der deinen Code aufheben würde, hätte viel leichter die Aufgabe, ihn mit einer korrekt definierten Vererbung zu verstehen.

Das Ziel eines guten Code-Designs ist nicht wirklich den kürzestmöglichen Code zu schreiben. Es geht um effizienten, aber auch klaren und selbst dokumentierten Code.

Zur Vollständigkeit meiner Antwort habe ich einige der in anderen Antworten angesprochenen Punkte wiederholt - keine Missachtung beabsichtigt.

    
Szymon 19.10.2013 08:12
quelle
2

In Ihrem speziellen Fall sollte Shape ein interface nicht ein abstract class sein. Ein interface ist im Grunde ein abstract class mit nur public Methoden und keine Implementierungen. Ein abstract class macht Sinn, wenn Sie in der Lage sind, eine bestimmte Methode zu implementieren, die für alle oder zumindest die meisten implementierenden Subklassen korrekt ist. Es ist eine Anwendung des DRY-Prinzips in diesem Fall.

Warum sollten Sie sich mit abstrakten Klassen oder Interfaces beschäftigen?

Weil du jetzt nur ein List<Shape> haben kannst, wo du alle Arten von verschiedenen Formen einfügen kannst und du brauchst dich nicht darum zu kümmern, welche Form es genau ist. Die JVM erledigt die Arbeit für Sie und wählt aus, welche getArea Implementierung sie wählen soll.

    
noone 19.10.2013 08:07
quelle

Tags und Links

Django: Verwenden von Annotate, Count und Distinct in einem Queryset ___ qstntxt ___

Nach dieser jsbin habe ich eine %code% -Liste und eine Schaltfläche. Wenn Sie auf den Button klicken, fügen Sie zu %code% hinzu und ich möchte wissen, welches Ereignis von %code% ausgelöst wurde (update, receive) und wenn Sie das Ereignis gefunden haben, machen Sie etwas für dieses Ereignis.

Wenn der Benutzer zum Beispiel auf %code% button klickt, möchte ich wissen, welches Ereignis ausgelöst wird und etwas für das Ereignis tun. zum Beispiel, wenn Update Feuer mache ich etwas in Update-Methode von sortierbaren

%Vor%     
___ tag123jqueryui ___ jQuery UI ist ein kuratierter Satz von Benutzeroberflächeninteraktionen, Effekten, Widgets und Designs, die auf der jQuery-JavaScript-Bibliothek basieren. ___ tag123jqueryuisortable ___ Das jQuery UI Sortierbare Plugin macht ausgewählte Elemente durch Ziehen mit der Maus sortierbar. ___ answer23516999 ___

Verwenden Sie die %code% -Methode von der Sortierung (um ihre Callbacks abzurufen)

Da der Aktualisierungsrückruf als Option des sortierbaren Widgets definiert ist, kann er als solcher durch Aufruf der optionsmethode :

%Vor%

Der Updaterückruf erwartet zwei Parameter , die %code% und eine %code% . Der %code% kann auf null gesetzt werden und der %code% muss mit allen Eigenschaften definiert werden, die Ihr %code% erwartet:

%Vor%

Arbeiten von JS-Fiddle

    
___ tag123jquery ___ jQuery ist eine beliebte Cross-Browser-JavaScript-Bibliothek, die das DOM-Traversal (Document Object Model), die Ereignisbehandlung, Animationen und AJAX-Interaktionen erleichtert, indem die Diskrepanzen zwischen Browsern minimiert werden. Eine mit jQuery gekennzeichnete Frage sollte mit jQuery in Zusammenhang stehen, daher sollte jquery von dem fraglichen Code verwendet werden, und mindestens eine jquery-nutzungsbezogene Elemente müssen in der Frage enthalten sein. ___ answer19344119 ___

Das Problem

Wenn Sie den %code% -Rückruf als Teil der Widget-Optionen %code% definieren, wird ein Ereignis namens %code% an das Widget gebunden. Mit anderen Worten, die Callback-Funktion, die durch die %code% -Option definiert ist, wird zwar aufgerufen, aber ein Ereignis mit diesem Namen wird in dieser Situation nicht ausgelöst.

Die Lösung

Wenn Sie das Ereignis manuell auslösen möchten, müssen Sie es auch manuell binden . Beachten Sie, dass das Ereignis auch automatisch vom normalen Verhalten des Widgets ausgelöst wird (z. B. wenn ein Benutzer die Elemente im Widget sortiert).

Zum Beispiel:

HTML

%Vor%

JS

%Vor%

Siehe JS Bin Demo

    
___