Delphi: Wartbarkeit virtuell vs virtuell abstrakt

8

Ich habe vor ein paar Monaten eine Menge Code geschrieben und jetzt füge ich Dinge hinzu. Ich erkannte, dass ich eine Reihe von Funktionen geschrieben habe, die von einer Klasse abstammen, die etwa 2/3 ihrer Funktionen abstrakt und die verbleibende 1/3 virtuell hat.

Ich bin es ziemlich leid zu sehen:

%Vor%

wenn ich dies für die Basisklasse habe:

%Vor%

und würde es hassen mit:

%Vor%

und frage mich dann, warum etwas nicht funktioniert hat.

Ich verwende gerne abstrakte Funktionen, weil der Compiler Sie wissen lässt, ob Sie einen abstrakten Fehler bekommen, weil Sie einige Funktionen nicht implementiert haben.

Meine Frage ist, weil ich immer noch ein relativ neuer Delphi-Programmierer bin und ich in acht Jahren noch nie etwas gepflegt habe, lohnt es sich, sich die Zeit zu nehmen, deinen Code auf diese Weise beschneiden (dh Funktionen entfernen, die in ihnen geerbt wurden und deine Basisklassenfunktionen von abstrakt in konkret ändern)

    
Peter Turner 27.09.2010, 15:52
quelle

3 Antworten

7

Es hängt wie immer vom Problem ab. Ich benutze Schnittstellen, um die Benutzeroberfläche für den Satz von Klassen zu definieren. Zumindest wenn ich weiß, dass ich mehr als eine Implementierung der eigentlichen Klasse haben werde. Zum Beispiel können Sie so etwas haben:

%Vor%

Hier haben Sie keinen gemeinsamen Vorfahren. Jede Klasse implementiert nur die Schnittstelle und hat keine gemeinsame zugrunde liegende Struktur in Form einer gemeinsamen Basisklasse. Dies ist möglich, wenn die Implementierungen so unterschiedlich sind, dass sie nichts gemeinsam haben, sondern sich selbst verbinden. Sie müssen immer noch dieselbe Schnittstelle verwenden, damit Sie gegenüber den Benutzern der abgeleiteten Klassen konsistent sind.

Die zweite Option ist:

%Vor%

Hier haben Sie eine Basisklasse für alle Klassen. In dieser Klasse können Sie allgemeine Eigenschaften oder Ereignisse, andere Klassen usw. haben. Alle Prozeduren sind jedoch als abstrakt gekennzeichnet, da sie keine allgemeinen Aufgaben ausführen. Abstract stellt sicher, dass sie in den abgeleiteten Klassen implementiert werden, aber Sie müssen "FieldA" nicht in jeder Klasse implementieren, Sie implementieren es nur in "TAllAbstract_Custom". Dies stellt sicher, dass das DRY-Prinzip verwendet wird.

Die letzte Option ist:

%Vor%

Hier haben alle abgeleiteten Klassen eine gemeinsame virtuelle Basisprozedur. Dies stellt sicher, dass Sie nicht jede einzelne Prozedur auf der Ebene der abgeleiteten Klassen implementieren müssen. Sie können nur einige Teile des Codes oder gar keine außer Kraft setzen.

Natürlich sind das alle Randfälle, da ist Platz in ihnen. Sie können eine Mischung dieser Konzepte haben.

Denken Sie daran:

  1. Schnittstellen sind ein leistungsstarkes Werkzeug, um sicherzustellen, dass Sie die Implementierung vor dem Benutzer verbergen und einen gemeinsamen Nutzungspunkt (Schnittstelle) haben. Sie zwingen auch, dass einige Normen verwendet werden, weil die Schnittstelle vollständig implementiert werden muss.
  2. Abstract ist ein gutes Werkzeug, damit Sie keine leeren Stubs für Prozeduren verwenden müssen, wo sie nicht wirklich benötigt werden. Auf der anderen Seite zwingen sie Sie, sie in abgeleiteten Klassen zu implementieren.
  3. Virtual ist praktisch, wenn Sie einen gemeinsamen Code haben, der von jeder Klasse implementiert werden muss und der das saubere OP- und DRY-Prinzip gewährleistet. Sie sind auch willkommen, wenn Sie Prozeduren haben, die nicht jede abgeleitete Klasse hat oder braucht.

Sorry für eine lange Antwort, aber ich konnte hier keine einfache Erklärung geben, weil es keine gibt. Es hängt alles von dem Problem ab. Es ist ein Gleichgewicht zwischen dem, was die abgeleiteten Klassen gemeinsam haben und wie unterschiedlich ihre Implementierungen sind.

    
Runner 27.09.2010 17:03
quelle
1

Wenn der Code wirklich einfach ist und Sie es schwierig finden, ihn zu lesen und fehleranfällig zu machen, ist er wahrscheinlich schwer zu lesen und fehleranfällig. (Andererseits, wenn der Code kompliziert ist und Sie es schwer finden, ihn zu lesen, könnte es Ihr Mangel an Erfahrung sein. Aber nicht so etwas.) Sie würden wahrscheinlich gut tun, um es zu refaktorisieren jetzt, während das Problem noch frisch in deinen Gedanken ist.

    
Mason Wheeler 27.09.2010 16:13
quelle
1

Ja, beschneiden Sie Ihren Code.

Es macht Ihren anderen Code viel einfacher zu lesen (wie Sie bereits erwähnt haben, wäre es einfacher zu sehen, welche Methoden tatsächlich überschrieben werden). Als zusätzlichen Vorteil wird es einfacher sein, die Signatur der Methode in der Elternklasse zu ändern: Stellen Sie sich vor, Sie entscheiden sich, einen weiteren Parameter an eine virtuelle Methode zu übergeben; Wenn Sie die Änderung an der übergeordneten Klasse vornehmen, müssen Sie diese Änderung für jede untergeordnete Klasse wiederholen, die von der angegebenen übergeordneten Klasse erbt. An diesem Punkt wollen Sie keine falschen überschriebenen Methoden, die nur "geerbt" aufrufen!

    
Cosmin Prund 28.09.2010 10:21
quelle