Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Set- und Getter-Methoden (https://www.delphipraxis.net/180407-set-und-getter-methoden.html)

ThaiSon96 18. Mai 2014 17:32

Set- und Getter-Methoden
 
Hallo,
wir bearbeiten gerade in der Schule das Thema "Klassen". Wir sollen dabei immer Set- und Getter-Methoden benutzen.
Bis jetzt habe ich immer nur Set-Methoden benutzt, die Getter-Methoden habe ich immer weggelassen und es hat dann meistens in Delphi 7 auch geklappt.
Ich habe das jetzt so verstanden, dass man die Set-Methoden braucht, um Werte sozusagen "in die Klasse zu übergeben", damit man dort mit ihnen weiterarbeiten kann.
Liege ich da richtig? Was ist der Sinn hinter den beiden oben genannten Methoden?
Über Antworten würde ich mich freuen.
P.S.: Falls ihr versucht, mir zuhelfen, dann versucht es bitte so vereinfacht wie möglich zu erklären! Danke im Voraus.

mkinzler 18. Mai 2014 17:45

AW: Set- und Getter-Methoden
 
Das ist Teil des information hiding. Die Eigenschaften sind privat und nur über Getter/Setter zugreifbar.
In Sprachen wie Java wird so etwas praktiziert. Um das RAD Prinzip zu unterstützen, wurde in Delphi die Property eingeführt, wie sich nach aussen als offentliche Eigenschaft zeigt; welche aber "Virtuell" ist.
Die Zugriffe auf diese werden direkt auf die entsprechende private Variable oder auf Getter/Setter umgeleitet.

Namenloser 18. Mai 2014 17:46

AW: Set- und Getter-Methoden
 
Es geht vor allem darum, eine einheitliche Schnittstelle zu haben.

Zum Beispiel könnte es ja sein, dass der Wert der Variablen nicht direkt im Programm (im Arbeitsspeicher) gespeichert wird, sondern in einer externen Datenbank. Dann würde der Getter den Wert aus der Datenbank laden und der Setter würde den Wert in die Datenbank schreiben.

Es wäre auch möglich, dass man die Art der Speicherung im Nachhinein umbaut – z.B. wurden die Werte zunächst im Arbeitsspeicher gespeichert, und dann später hat man sich dafür entschieden, eine Datenbank zu verwenden. Dann muss man den Code nur an der entsprechenden Stelle anpassen und nicht jede Stelle im Programm, wo auf diese Eigenschaft zugegriffen wurde.

Außerdem hat ein Setter den Vorteil, dass man weitere Aktionen ausführen kann. Hat man z.B. einen Button mit der Eigenschaft „Farbe“, dann kann man beim Setzen der Farbe auch gleich noch ein Neuzeichnen des Buttons anstoßen.

Allerdings gibt es unter Delphi ein wesentlich eleganteres Konzept als Getter und Setter, und zwar Properties. In Fällen, wo Getter und Setter sowieso nur aus Einzeilern bestehen würden, die den Wert einer Variablen zurückliefern oder setzen, kann man sie gleich komplett weglassen und bläht sich so den Code nicht unnötig auf. Außerdem sieht der Zugriff auf eine Property genau so aus wie der Zugriff auf eine normale Variable, was stilistisch schöner ist (aber wohl auch Geschmackssache).

ThaiSon96 18. Mai 2014 17:58

AW: Set- und Getter-Methoden
 
Danke für die Antworten!
@Namenloser: Kannst du eventuell ein Beispiel für diese Methoden anhand deines Beispiels mit der Datenbank schicken? Das wäre sehr hilfreich! :-D

Namenloser 18. Mai 2014 18:01

AW: Set- und Getter-Methoden
 
Ein konkretes Code-Beispiel hab ich leider nicht. Da musst du deine Fantasie einsetzen :wink:

Sir Rufo 18. Mai 2014 18:07

AW: Set- und Getter-Methoden
 
Zitat:

Zitat von ThaiSon96 (Beitrag 1259207)
Danke für die Antworten!
@Namenloser: Kannst du eventuell ein Beispiel für diese Methoden anhand deines Beispiels mit der Datenbank schicken? Das wäre sehr hilfreich! :-D

Schreib du doch mal ein Beispiel und was du dort erklärt haben möchtest, das wäre auch sehr hilfreich ;)

Perlsau 18. Mai 2014 20:59

AW: Set- und Getter-Methoden
 
Zitat:

Zitat von ThaiSon96 (Beitrag 1259207)
... ein Beispiel für diese Methoden anhand deines Beispiels mit der Datenbank schicken? Das wäre sehr hilfreich! :-D

Beispiel für ein Property, das gelesen und geschrieben werden kann:
Delphi-Quellcode:
UNIT UnitData;

INTERFACE

USES
  SysUtils, Classes, DB, ADODB;

TYPE
  TDatMod = CLASS(TDataModule)
    AConMain    : TADOConnection;

  PRIVATE { Private-Deklarationen }
    fPfadMain : String;

    Function GetfPadMain: String;
    Procedure SetfPfadMain(const Value: String);

  PUBLIC { Public-Deklarationen }

    Property PfadMain : String Read GetfPadMain Write SetfPfadMain;
END;

VAR
  DatMod : TDatMod;

IMPLEMENTATION
{$R *.dfm}
{ TDatMod }

// *************** PRIVATE METHODEN ******************

// ---------- PFADMAIN - GET -------------------------
Function TDatMod.GetfPadMain: String;
begin
  Result := fPfadMain;
end;

// ---------- PFADMAIN - SET -------------------------
Procedure TDatMod.SetfPfadMain(const Value: String);
begin
  fPfadMain := Value;
end;

// *************** PUBLIC METHODEN *******************

// *************** ERGEIGNISSE ***********************

end.

himitsu 19. Mai 2014 08:50

AW: Set- und Getter-Methoden
 
Man kann das auch für Weiterleitungen nutzen.
z.B. in einer untergeordneten Komponente werden die Daten eigentlich gespeichert, aber im parent gibt es dennoch ein Property, um direkt darauf zuzugreifen.

Oder man erstellt den Rückgabewert erst im Getter.

z.B.
Delphi-Quellcode:
property Uhrzeit: TTime read GetTime;


Oder das Property LineBreak der TStringList. Dieses hat standardmäßig keinen Wert und gibt nur den Inhalt der globalen Konstante SLineBreak zurück.
Erst wenn man etwas zuweist (Setter), dann existiert der "private" Wert, welcher nun zurückgegeben wird.

bernau 19. Mai 2014 09:05

AW: Set- und Getter-Methoden
 
Zitat:

Zitat von himitsu (Beitrag 1259259)
Oder man erstellt den Rückgabewert erst im Getter.

z.B.

Delphi-Quellcode:
property Uhrzeit: TTime read GetTime;



Will jetzt nicht die Diskussion in eine andere Richtung leiten, aber es interessiert mich einfach.

Was für ein Sinn mach ein Property ohne Setter. Dann kann ich doch gleich eine Function daraus machen.

Jumpy 19. Mai 2014 09:51

AW: Set- und Getter-Methoden
 
Zitat:

Zitat von bernau (Beitrag 1259264)
Was für ein Sinn mach ein Property ohne Setter. Dann kann ich doch gleich eine Function daraus machen.


Das kann z.B. für lazy initialisation (heißt das so?) interessant sein:

Delphi-Quellcode:
Type TFoo=Class
  private
    fBar:TBar;
    function getBar:TBar;
  public
    Property Bar:TBar read getBar;
  end;

//....

function TFoo.getBar:TBar;
begin
  if fBar=nil then
    begin
    fBar:=TBAr.create;
    //...
    end;
  Result:=fBar;
end;

DeddyH 19. Mai 2014 09:59

AW: Set- und Getter-Methoden
 
Vom logischen Fehler (fBar nur dann erzeugen, wenn es nicht nil ist?) abgesehen bekäme man dasselbe Ergebnis, wenn Bar keine Property, sondern direkt die getBar-Funktion wäre. IMO hat die Property eher mit dem Information Hiding zu tun, den Anwender der Klasse sollte es nicht interessieren, ob hinter der Eigenschaft tatsächlich eine Funktion steckt oder nicht, es genügt, wenn er weiß, dass er sie nicht beschreiben kann.

Sir Rufo 19. Mai 2014 10:07

AW: Set- und Getter-Methoden
 
Im OI werden Funktionen nicht angezeigt, dafür aber Eigenschaften ;)

DeddyH 19. Mai 2014 10:09

AW: Set- und Getter-Methoden
 
Aber auch nur diejenigen im published-Abschnitt. Und ob es Sinn macht, eine ReadOnly-Property im OI anzuzeigen, muss man sich im Einzelfall überlegen.

Sir Rufo 19. Mai 2014 10:11

AW: Set- und Getter-Methoden
 
Zitat:

Zitat von DeddyH (Beitrag 1259290)
Aber auch nur diejenigen im published-Abschnitt. Und ob es Sinn macht, eine ReadOnly-Property im OI anzuzeigen, muss man sich im Einzelfall überlegen.

Wenn es sich um eine Instanz handelt Delphi-Referenz durchsuchenTLabeledEdit.EditLabel ;)

DeddyH 19. Mai 2014 10:16

AW: Set- und Getter-Methoden
 
Ich sag ja nicht, dass das grundsätzlich Quatsch ist, aber es ist eben auch nicht immer sinnvoll (manche Komponenten zeigen z.B. ihre Version im OI an). Dinge wie z.B. eine Count-Eigenschaft muss man ja nicht unbedingt zur Designtime verfügbar machen.

Jumpy 19. Mai 2014 10:52

AW: Set- und Getter-Methoden
 
Zitat:

Zitat von DeddyH (Beitrag 1259285)
Vom logischen Fehler (fBar nur dann erzeugen, wenn es nicht nil ist?) abgesehen bekäme man dasselbe Ergebnis, wenn Bar keine Property, sondern direkt die getBar-Funktion wäre.

:oops: Ja sorry, denkfehler. <> ist jetzt =.

Natürlich geht das auch nur mit einer Funktion ohne Property, aber wenn man denn alles mit Properties macht, wäre das ein Beispiel für eine Read-Only Property.

Aber kann mas es denn nicht auch ein bißchen anhand der tatsächlichen Begrifflichkeiten definieren? Was ist eine Funktion des Objektes, was ist eine Methode?

Beispiel:
Delphi-Quellcode:
TPerson=class
  private
    fVorname:String;
    fNachname:String;
    function getName:String;
   public
    property Vorname:String read fVorname write fVorname;
    property Nachame:String read fNachname write fNachname;
    property Name:String read getName;
end;

TPerson.getName:String;
begin
  Result:=Vorname+' '+Nachname;
end;
Imho ist Name halt auch eine Eigenschaft der Person, drum als Property umgesetzt.
Die getName Funktion public gemacht und in Name umgewandelt würde auch gehen, aber irgendwie würde mich da was stören. Ist ja schon fast eine philosophische Frage. :)

(Das Name u.U. ein schlechter Name für eine Eigenchaft ist, sei mal aussen vor gelassen).

DeddyH 19. Mai 2014 10:56

AW: Set- und Getter-Methoden
 
Ich gebe Dir da völlig Recht und wollte vorhin nur aufzeigen, dass man technisch gesehen für lazy initialization nicht zwingend eine Property braucht. Ich würde das allerdings auch als Eigenschaft und somit Property ansehen und deshalb genauso schreiben.

ThaiSon96 19. Mai 2014 16:09

AW: Set- und Getter-Methoden
 
Auf jeden Fall sollten wir zunächst mal unsere Klassen in Klassendiagrammen darstellen (mit UML-Editor). Dabei sollte man für die versch. Attribute Lese- und Schreibanfragen erstellen (einfach Häkchen setzen). Das Programm hat dann immer für die Methoden dann "GetAttribut1" und/oder "SetAttribut1" in das Diagramm geschrieben, weshalb ich mich gefragt habe, wozu man diese beiden überhaupt braucht. Normalerweise schreibe ich einfach irgendwelche Funktionen oder Prozeduren...ansonsten hat sich das Thema eigentlich erledigt, weil das was ihr in euren Programmcodes angebt, hatte ich noch nicht. Trotzdem Danke für die Antworten!

himitsu 19. Mai 2014 18:53

AW: Set- und Getter-Methoden
 
Oder als Info-Property im OI, welches dem Entwickler irgendeinen Statuswert anzeigt.

Und im Code funktioniert auch nicht immer alles.
Delphi-Quellcode:
if Assigned(MyObj.MyProp) then
ging bisher immer, während
Delphi-Quellcode:
if Assigned(MyObj.MyFunction) then
manchmal vom Compiler abgewiesen wurde. (je nach Typ)

bernau 20. Mai 2014 08:18

AW: Set- und Getter-Methoden
 
Zitat:

Zitat von DeddyH (Beitrag 1259311)
Ich würde das allerdings auch als Eigenschaft und somit Property ansehen und deshalb genauso schreiben.

Wenn ich genauer drüber nachdenke, ist dies das Argument, wann man Property (readOnly) und wann man Function verwendet.

Property verwendet man für Eigenschaften wie "Laenge", "Breite", "Geschwindigkeit" etc.

Funktionen werden für Berechnungen etc. verwendet. Somit sollte im Funktionsnamen ein Verb vorhanden sein.

Habe bisher auch für Readonly-Eigenschaften "function" verwendet. Macht aber Sinn zukünftig property zu verwenden.

(Da muss ich 20 Jahre programmieren, damit mir solche trivialen Dinge auffallen :oops: )

Dejan Vu 20. Mai 2014 09:42

AW: Set- und Getter-Methoden
 
Zitat:

Zitat von bernau (Beitrag 1259465)
Somit sollte im Funktionsnamen ein Verb vorhanden sein.

Ach, echt? wo ist denn jetzt in 'Sqrt', 'Ln', 'Sin', 'Cos' etc. das Verb? Fang bloß nicht an mit diesem Quark und zwinge dich dazu, das immer so machen zu müssen. Das führt zu verkrampft-gewollten Bezeichnern.
Richtig sollte es imho heißen : 'Somit sollte eigentlich...'. ;-) Meistens passt das, aber eben auch nicht immer.


Ich peitsche gerade einige Programmierer im Geiste, die das hier durchsetzen wollen.

PS: Ganz schlimm ist es, wenn man darauf besteht, das jede Funktion immer 'GetXXXX' heißen muss.

DeddyH 20. Mai 2014 09:44

AW: Set- und Getter-Methoden
 
"Sollte" <> "muss". Wollen wir jetzt noch ein paar Erbsen zählen oder Haare spalten?

Sir Rufo 20. Mai 2014 10:44

AW: Set- und Getter-Methoden
 
Bei reinen Funktionen macht das weniger Sinn, bei Methoden schon eher.

Allerdings immer nur
Delphi-Quellcode:
Get...
ist natürlich auch blind.

Delphi-Quellcode:
AsString
,
Delphi-Quellcode:
ToString
,
Delphi-Quellcode:
GetHashCode
,
Delphi-Quellcode:
Equals
finde ich im verwendeten Kontext richtig.

Bei einer Factory kann man sich streiten, ob
Delphi-Quellcode:
GetInstance
oder
Delphi-Quellcode:
Build
, allerdings präferiere ich hier
Delphi-Quellcode:
Build
, denn das ist aussagekräftiger mMn.

(ok,
Delphi-Quellcode:
AsString
ist eine Eigenschaft, ziehen wir also einen ab :))

Dejan Vu 20. Mai 2014 11:03

AW: Set- und Getter-Methoden
 
Zitat:

Zitat von DeddyH (Beitrag 1259480)
"Sollte" <> "muss". Wollen wir jetzt noch ein paar Erbsen zählen oder Haare spalten?

Ich würde das jetzt nicht als Erbsenzählen ansehen, sondern als kleine Warnung (aus eigener Erfahrung) oder Anekdote bzw. Schwank aus meiner Jugend. Sieh es, wie Du willst. Und natürlich: wenn Nomenklatur für dich Haarspalterei ist, auch als Haarspalterei.

Wichtig ist doch, sich Gedanken darüber zu machen ('Funktion dann, wenn der Name/Die Beschreibung ein Verb enthält') und zu wissen, das man unabhängig davon einen Namen wählen sollkannmussdarfmachdocheinfachwasduwillst, der einfach passt und einfach ist.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:50 Uhr.

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