Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   vererbende Klasse oder Interface? oder beides? (https://www.delphipraxis.net/177208-vererbende-klasse-oder-interface-oder-beides.html)

Vis 24. Okt 2013 14:30

vererbende Klasse oder Interface? oder beides?
 
Hallo. Ich bin gerade am kämpfen/lernen mit Vererbung und Interfaces und bräuchte da mal eine kompetente Meinung.

Meine Problemstellung:
Ich habe verschiedene Messgeräte die ich über GPIB anspreche. Das Schreiben/Lesen ist bei den Messgeräten unterschiedlich. Deshalb wollte ich ein Interface ISchreibenLesen verwenden, dessen Methoden dann jede Klasse implementieren muss. Theoretisch könnte ich ja aber auch abstrakte Methoden in der Oberklasse deklarieren und diese dann jeweils in der Unterklasse überschreiben. Kann man da sagen was besser ist?
Die Oberklasse hatte ich mir gedacht, da ja alle Messgeräte gewisse gemeinsame Felder besitzen (Adresse usw.)

TMessgeräte = class ((TInterfacedObject))

TMessgerätA = class (TMessgeräte, ISchreibenLesen) TMessgerätB = class (TMessgeräte, ISchreibenLesen)


Und noch eine Frage. Die Messgeräte sollen eine Property Range bekommen (mit Getter und Setter).
In der Oberklasse deklariert, wird die Property an die Unterklassen vererbt, die Getter/Setter müssten dann abstract sein. Oder anders, die Property im Interface deklarieren (hier auch Getter/Setter). Dann muss ich in der Unterklasse aber wieder eine Property deklarieren, das wird irgendwie doch nicht mehr so übersichtlich.

Wie würdet ihr sowas machen? Wie gesagt, bin da noch stark am Anfang mit Interfaces und Vererbung und für jede Anregung dankbar.

Grüße

Uwe Raabe 24. Okt 2013 15:04

AW: vererbende Klasse oder Interface? oder beides?
 
Ob besser oder schlechter kann man hier nicht sagen. Das kommt wesentlich auf den Rest der Anwendung an. Interfaces bieten Referenzzählung, blähen den Code aber auch etwas auf. Wenn du alles auf einen gemeinsamen Vorfahren zurückführen kannst, ist eine abstrakte Klasse auch keine schlechte Wahl.

Die Getter und Setter kannst du problemlos als abstract deklarieren. Die abgeleitete Klasse braucht dann auch nicht das Property nochmal zu deklarieren - es genügt, wenn die Getter und Setter überschrieben werden.

romankassebaum 24. Okt 2013 20:44

AW: vererbende Klasse oder Interface? oder beides?
 
Hallo,

Interfaces bieten zwei grundlegende Vorteile:

1. Durch die Referenzzählung müssen Sie nicht explizit freigegeben werden.
2. Ein Interface kann von verschiedenen Objekten implementiert werden, die gerade nicht über einen gemeinsamen Vorfahren verfügen.

Da Du in Deinem Beispiel den gemeinsamen Vorfahren TMessgerät hast, denke ich, dass Du keine Interfaces benötigst.

In Deinem Beispiel kannst Du übrigens bereits das TMessgerät mit dem Interface ISchreibenLesen verbinden, da die Erben es ohnehin bereitstellen sollen.

--
Viele Grüße,

Roman Kassebaum
Embarcadero Technology Partner
Embarcadero MVP
Blog: http://blog.kassebaum.eu

Vis 25. Okt 2013 07:49

AW: vererbende Klasse oder Interface? oder beides?
 
Ok, Danke. Das war schon mal sehr interessant.

Wenn ich das Interface ISchreibenLesen mit der Oberklasse TMessgeräte verbinde, dann müsste ich doch eigentlich die Methoden auch in TMessgeräte implementieren. Das möchte ich ja aber erst in den abgeleiteten Klassen. Also müsste ich ja folglich die vom Interface bereitgestellten Methoden als abstract deklarieren. In meinem Fall ist das vielleicht zuviel des Guten und ich deklariere die Methoden gleich in TMessgeräte ohne das Interface. Ansonsten wäre ja 3-mal eine Methode deklariert (im Interface, Oberklasse, Unterklasse) + die Implementierung. Das kann schon auch unübersichtlich werden.

Werd mich mal ran machen das umzusetzen!

Der schöne Günther 25. Okt 2013 10:27

AW: vererbende Klasse oder Interface? oder beides?
 
Genau das gefällt mir auch nicht wirklich. Die Schuld liegt da irgendwie eher an der Delphi-Sprache selber, "echte" abstrakte Klassen kennt es nicht.

Delphi-Quellcode:
   INeustartbar = interface
   ['{C952DFE2-65A3-48A4-8681-81F97946DB5A}']
      procedure restart();
   end;

   ISchreibenLesen = interface
   ['{DBAF7078-C915-471F-8C37-F679253220BE}']
      procedure writeStuff();
      procedure readStuff();
   end;
                                                                  (
   AMessgerät = class abstract(TInterfacedObject, ISchreibenLesen)
      public // Warum ist das hier überhaupt notwendig?
         procedure readStuff; virtual; abstract;
         procedure writeStuff; virtual; abstract;
   end;

   TMessgerät1 = class(AMessgerät)
      procedure spezialKram();
   end;

   TMessgerät2 = class(AMessgerät, INeustartbar)
      public
         procedure spezialKram();
         procedure restart();
   end;

romankassebaum 25. Okt 2013 22:27

AW: vererbende Klasse oder Interface? oder beides?
 
Ich hatte ja gestern schon gesagt, dass man Interfaces sehr gut nutzen kann, um Objekte, die keinen gemeinsamen Vorfahren habe, anzusprechen.
Für die zweite Aufgabe, die Referenzzählung, kann man übrigens auch einen ObjGuard (http://blog.kassebaum.eu/?p=87) nehmen.

Was mir an der vorgestellten Lösung überhaupt nicht gefällt, ist, dass man von TInterfacedObject ableiten muss. Dadurch "weiß" TMessgerät bereits, dass die abgeleiteten Klassen Interfaces nutzen werden.

Ich würde also die Interfaces weglassen.

--
Roman Kassebaum
Embarcadero Technology Partner
Embarcadero MVP
Blog: http://blog.kassebaum.eu

jaenicke 26. Okt 2013 08:33

AW: vererbende Klasse oder Interface? oder beides?
 
Delphi-Quellcode:
   INeustartbar = interface
   ['{C952DFE2-65A3-48A4-8681-81F97946DB5A}']
     procedure restart();
   end;

   ISchreibenLesen = interface
   ['{DBAF7078-C915-471F-8C37-F679253220BE}']
     procedure writeStuff();
     procedure readStuff();
   end;
                                                                 
   TMessgerät = class abstract(TInterfacedObject)
   end;

   TMessgerät1 = class(TMessgerät, ISchreibenLesen)
     procedure readStuff;
     procedure writeStuff;
     procedure spezialKram();
   end;

   TMessgerät2 = class(TMessgerät, ISchreibenLesen, INeustartbar)
   public
     procedure readStuff;
     procedure writeStuff;
     procedure spezialKram();
     procedure restart();
   end;
Das geht genauso. Das Interface muss man ja nicht in der Oberklasse angeben.
Delphi-Quellcode:
var
  a: TMessgerät;
  b: ISchreibenLesen;
begin
  a := TMessgerät2.Create;
  b := a as ISchreibenLesen;
  b.readStuff;
end;
(Wobei das Objekt nach der Methode durch das Interface freigegeben wird.)

// EDIT:
Zitat:

Zitat von romankassebaum (Beitrag 1233232)
Was mir an der vorgestellten Lösung überhaupt nicht gefällt, ist, dass man von TInterfacedObject ableiten muss. Dadurch "weiß" TMessgerät bereits, dass die abgeleiteten Klassen Interfaces nutzen werden.

Warum muss man? Man kann die notwendigen Methoden (QueryInterface, ...) auch in den Unterklassen implementieren. Ich halte das nicht für sinnvoll, kann man aber. Man verliert dann aber die Möglichkeit von der Oberklasse auf das Interface zu casten.

romankassebaum 26. Okt 2013 08:53

AW: vererbende Klasse oder Interface? oder beides?
 
Es ist ganz wichtig, dass Du die Objektinstanz nicht in einer Variablen merkst. Sobald die Referenzzählung das Objekt freigibt, wäre die Instanz nicht mehr gültig.

Delphi-Quellcode:
var
  b: ISchreibenLesen;
begin
  b := TMessgerät2.Create;
  b.readStuff;
end;
--
Roman Kassebaum
Embarcadero Technology Partner
Embarcadero MVP
Blog: http://blog.kassebaum.eu

jaenicke 26. Okt 2013 09:55

AW: vererbende Klasse oder Interface? oder beides?
 
Außer zur Initialisierung in einer lokalen Variable, da finde ich das in Ordnung. Aber sobald das Objekt das erste Mal in einer Interfacereferenz gelandet ist, darf man die Objektvariable natürlich nicht mehr nutzen.

Deshalb ist es auch besser entweder Interfaces oder Objekte zu nutzen und das durch die gesamte Vererbung durch.

Oder man deaktiviert die Referenzzählung.

sx2008 26. Okt 2013 12:44

AW: vererbende Klasse oder Interface? oder beides?
 
Ich würde Datentransport und Datenaufbereitung strikt voreinander trennen.
Das bedeutet dass es eine Klasse für GPIB gibt die rein nur für den Datentransport zuständig ist
und eine weitere (Basis-)Klasse TMessGeraet die für die Aufbereitung der Daten verantwortlich ist.

Dabei benützt die Klasse TMessGeraet ihren Kollegen TGPIB. (Assoziation).

Es liegt also weder eine Vererbung vor noch benötigt man ein Interface.
Man könnte sogar eine weitere Klasse für das Datenprotokoll einsetzen falls ein einheitliches Protokoll wie CS-80 (Command Set 80) benützt wird.

Man kann diesen Ansatz mit folgender Kette vergleichen:
Code:
TDatabase <- TQuery <- TDBEdit
TDatabase sorgt für den Datentransport
TQuery entspricht praktisch dem Protokoll auf Datenbankebene und
TDBEdit repräsentiert die Daten auf Anwendungsebene.

Jede Klasse dient nur einem bestimmten Zweck wobei die Klassen miteinander kollaborieren und in einer "benützt"-Beziehung stehen.
Wichtig ist noch die Pfeilrichtung der Abhängigkeiten zu beachten.
Die Klasse TGPIB darf die Klasse TMessGeraet nicht kennen; umgekehrt kennt und benützt aber TMessgeraet die Klasse TGPIB.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:07 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz