AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi kleines OOP Beispiel bitte um Anmerk./Verbesserungvorschläge

kleines OOP Beispiel bitte um Anmerk./Verbesserungvorschläge

Offene Frage von "newbe"
Ein Thema von newbe · begonnen am 14. Okt 2008 · letzter Beitrag vom 17. Okt 2008
Antwort Antwort
Seite 2 von 3     12 3   
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#11

Re: kleines OOP Beispiel bitte um Anmerk./Verbesserungvorsch

  Alt 14. Okt 2008, 18:58
Dann lass doch den Setter bei Ergebnis weg und lass auch gleich fErgebnis weg und gebe bei GetErgebnis einfach die summe zurück.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.537 Beiträge
 
Delphi 11 Alexandria
 
#12

Re: kleines OOP Beispiel bitte um Anmerk./Verbesserungvorsch

  Alt 14. Okt 2008, 18:58
Du darfst dann auch nicht die Setter-Methoden direkt aufrufen, sondern müsstest die Properties setzen, welche dann wiederum in ihrem jeweiligen Setter die Berechnung durchführen können. Das kann auch durchaus sinnvoll sein, ich sehe da jetzt keinen Widerspruch zur OOP.

[edit]
Zusammengefasst könnte das dann so aussehen:
Delphi-Quellcode:
  TMeineDaten = class(TObject)
    private
      fWert1 : Integer;
      fWert2 : Integer;
      procedure SetWert1(const Value: Integer);
      procedure SetWert2(const Value: Integer);
      function GetErgebniss(): Integer;
    public
      property Wert1 : Integer read FWert1 write SetWert1 Default 0;
      property Wert2 : Integer read FWert2 write SetWert2 Default 0;
      property Ergebnis : Integer read GetErgebnis;
  end;

procedure TMeineDaten.SetWert1(const Value: Integer);
begin
  FWert1 := Value;
end;

procedure TMeineDaten.SetWert2(const Value: Integer);
begin
  FWert2 := Value;
end;

function TMeineDaten.GetErgebniss(): Integer;
begin
  Result := fWert1 + fWert2;
end;
[/edit]
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#13

Re: kleines OOP Beispiel bitte um Anmerk./Verbesserungvorsch

  Alt 14. Okt 2008, 19:55
Ich würde allerdings ie Getter uns Setter protected machen, um jemendem, der die Klasse ableiten möchte, das Leben nicht unnötig kompliziert zu machen

Ist aber nur eine klitzekleine Anregung, ich will ja keinen überfordern
  Mit Zitat antworten Zitat
newbe

Registriert seit: 14. Okt 2008
143 Beiträge
 
Delphi 7 Personal
 
#14

Re: kleines OOP Beispiel bitte um Anmerk./Verbesserungvorsch

  Alt 14. Okt 2008, 20:25
@DeddyH

bin begeistert von deinem Code.

Also das sieht doch echt schlank und elegant aus. Ich würde nur gern das Ergebnis im Object storen, da er ja sonst bei jedem
zugriff auf die Property diese Berechnung ausführt. Und das kann bei Komplexen sachen schon mächtig performance kosten.

Also sprich die Funktion GetErgebniss soll intern Checken ob die Berechnung schon ausgeführt wurde, und das Ergebnis dann
aus der Property fErgebnis holen, anstatt bei jedem zugriff nochmal zu berechnen.

Aber ansonsten finde ich deinen Code top. :Thumbs up:

mfG newbe
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#15

Re: kleines OOP Beispiel bitte um Anmerk./Verbesserungvorsch

  Alt 14. Okt 2008, 20:33
Delphi-Quellcode:
TMeineDaten = class(TObject)
    private
      fWert1 : Integer;
      fWert2 : Integer;
      FErgebnis: Integer;
      FBerechnet: Boolean;
      procedure SetWert1(const Value: Integer);
      procedure SetWert2(const Value: Integer);
      function GetErgebniss(): Integer;
    public
      property Wert1 : Integer read FWert1 write SetWert1 Default 0;
      property Wert2 : Integer read FWert2 write SetWert2 Default 0;
      property Ergebnis : Integer read GetErgebnis;
  end;

procedure TMeineDaten.SetWert1(const Value: Integer);
begin
  FWert1 := Value;
  FBerechnet:=false;
end;

procedure TMeineDaten.SetWert2(const Value: Integer);
begin
  FWert2 := Value;
  FBerechnet:=False;
end;

function TMeineDaten.GetErgebniss(): Integer;
begin
  if not FBerechnet then
  begin
    FErgebnis:= fWert1 + fWert2;
    FBerechnet:=true;
  end;
  result:= FErgebnis;
end;
Ist mir zu lang, dass jetzt zu erklären.
FBerechnet könnte man noch im constrcutor initialisieren.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
newbe

Registriert seit: 14. Okt 2008
143 Beiträge
 
Delphi 7 Personal
 
#16

Re: kleines OOP Beispiel bitte um Anmerk./Verbesserungvorsch

  Alt 15. Okt 2008, 04:52
@sirius

Genau so habe ich mir das vorgestellt.

Eine letzte Frage hätte ich noch zu dem Themenkomplex. Unzwar zum constructor. Du weist darauf hin, das es wichtig wäre
den Boolean zu initialisieren, was ja auch richtig ist. Jedoch verstehe ich eines nicht. Im Inet habe ich irgendwo aufgeschnappt,
das man Klassenvariablen bzw. Felder immer erst nach abgeschlossener Object-Erstellung initialisieren sollte. Ich habe das so verstanden, das ich erst das Object erstellen soll und erst dann eine extra Init Prozedure aufrufen soll um Seiteneffekte zu vermeiden. Also in dieser Art.

Delphi-Quellcode:

procedure bla.init;
begin

Wert1 : Integer = 0; //Initialisieren
Wert2 : Integer = 0;
Ergebnis: Integer = 0;
FBerechnet: Boolean = false;

end;

....

TForm1.buttonclick(Sender: TObject);
var bla: TMeineDaten;

begin

bla:=TMeineDaten.create;
bla.init;

end;
Stimmt das den jetzt, oder ist da was wahres dran? Kann ich jede Art von Klassenvariable im Constructor initialisieren oder
kann es da probleme geben weil die Objecterstellung ja im Constructor noch nicht abgeschlossen ist?

mfG newbe
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#17

Re: kleines OOP Beispiel bitte um Anmerk./Verbesserungvorsch

  Alt 15. Okt 2008, 07:56
Die Objekterstellung ist abgeschlossen, wenn du im constrcutor bist.
Der Code zum Erstellen der Instanz fügt der Compiler bei dem Wort "begin" des Constructors ein. Also, wie gesagt, direkt am Anfang.

Edit: Vielleicht mal konkret.
Jede Methode bekommt ja immer mindestens den Parameter "self" übergeben. Damit kannst du ja auf die Felder deiner Klasse zugreifen. Der Constructor bekommt zusätzlich noch einen Wert mitgegeben. Dieser sagt aus, ob der Constructor eine neue Instanz erstellen soll.

Hier mal eine normale Methode
Delphi-Quellcode:
//aus folgendem Code:
procedure TMeineDaten.SetWert1(const Value: Integer);
begin
  FWert1 := Value;
  FBerechnet:=false;
end;

//wird eigentlich:
procedure TMeineDaten.SetWert1(Self:Pointer; const Value: Integer);
begin
  Self.FWert1 := Value;
  Self.FBerechnet:=false;
end;
Und self zeigt einfach auf eine Art Record, in dem alle deiner Felder (Klassenvariablen) enthalten sind. Self ist dann auch das, was in deiner Objektinstanz "MeineDaten" (oder in Post #10: "test") steht. Ist halt einfach nur ein Zeiger auf deinen InstanzRecord. Und jede Instanz hat ihren eigenen Record.

So, und jetzt noch mal zum Constrcutor. Der hat, wie gesagt, neben "self" noch einen versteckten Parameter:
Delphi-Quellcode:
//aus folgendem Code:
Constructor TMeineDaten.Create;
begin
  fBerechnet:=false;
end;

//wird dann:
Constructor TMeineDaten.Create(Self:Pointer; doCreateClass:Boolean);
begin
  if doCreateClass then
  begin
    Self:=_ClassCreate(Self, True); //Ab hier existiert dein Objekt.
    Result:=Self;
  end;

  Self.fBerechnet:=false;


  if DoCreateClass then
    _AfterConstruction(Self);
end;
Was macht eigentlich _ClassCreate (neben Exceptionbehandlung und pipapo). Es reserviert einfach Speicher mittels new, wie bei einem normalen Record, den man dynamisch anlegt auch. Und dann wird die Adresse auf den Speicher zurückgegeben.

So, und jetzt gibt es zwei Aufrufmöglichkeiten des Constructors:
test:=TMeindeDaten.create; Hier wird DoCreateClass auf True gesetzt und anstatt Self wird ein Zeiger auf die TypInformationen von TMeineDaten übergeben (also TMeineDatenClass oder einfach TClass)
Wenn du jetzt den Constructor (irendwann nach der Instanzierung) nochmal so aufrufst (quasi, wie jede andere Methode auch):
test.create; dann ist DoCreateClass=False und an self wird eben der Wert von test übergeben (wie bei jeder anderen Methode auch).
Nebenbei: Wenn jetzt test noch nicht instanziert wäre und du einfach test.create aufrufst (Was ein typischer Delphi-Anfängerfehler ist), wird für self eben nil (oder ein anderer krummer Wert) übergeben und DoCreateClass ist natürlich false. Dann greifst du hier auf den Record nil.fBerechnet zu, was eine Access Violation, meist in der Nähe von Addresse 0 = nil, auslöst.

Allerdings ist es unüblich test.Create direkt aufzurufen. Der Zustand tritt eher ein, wenn man von TMeineDaten eine neue Klasse ableitet und dort, in einem neuen Constructor, dann inherited aufruft. Dann wird der Vorfahr, was TMeineDaten.Create ist, mit DoClassCreate=False aufgerufen.

Ich hoffe ich habe nicht zu sehr verwirrt. Hier ist es auch nochmal schön beschrieben.

Edit2:
Erst die Klasse instanzieren und dann einen weiteren Befehl zur Initialisierung aufrufen ist in anderen Sprachen (die wir hier nicht erwähnen wollen) notwendig. In Delphi kannst du instanzieren und initialisieren in einem Abwasch, eben im constructor, machen.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
newbe

Registriert seit: 14. Okt 2008
143 Beiträge
 
Delphi 7 Personal
 
#18

Re: kleines OOP Beispiel bitte um Anmerk./Verbesserungvorsch

  Alt 15. Okt 2008, 10:06
@sirius

Vielen Dank an Dich für deine ausführliche Erklärung dazu.

herzliche Grüße

newbe
  Mit Zitat antworten Zitat
newbe

Registriert seit: 14. Okt 2008
143 Beiträge
 
Delphi 7 Personal
 
#19

Re: kleines OOP Beispiel bitte um Anmerk./Verbesserungvorsch

  Alt 15. Okt 2008, 15:28
@All

Ich habe es jetzt so gemacht.

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;


TMeineDaten = class(TObject)
    private
      fWert1 : Integer;
      fWert2 : Integer;
      FErgebnis: Integer;
      FBerechnet: Boolean;
      procedure SetWert1(const Value: Integer);
      procedure SetWert2(const Value: Integer);
      function GetErgebniss: Integer;
    public
      constructor create;
      property Wert1 : Integer read FWert1 write SetWert1;
      property Wert2 : Integer read FWert2 write SetWert2;
      property Ergebnis : Integer read GetErgebniss;
  end;


var
  Form1: TForm1;

implementation

{$R *.dfm}



{ TMeineDaten }

procedure TMeineDaten.SetWert1(const Value: Integer);
begin

  if Value=5 then raise Exception.create('Wert 5 wird nicht als Eingabe akzeptiert!');

  FWert1 := Value;
  FBerechnet := false;
end;

procedure TMeineDaten.SetWert2(const Value: Integer);
begin

  if Value=5 then raise Exception.create('Wert 5 wird nicht als Eingabe akzeptiert!');

  FWert2 := Value;
  FBerechnet := false;
end;

constructor TMeineDaten.create;
begin
  FBerechnet := false;
end;

function TMeineDaten.GetErgebniss: Integer;
begin
  if not FBerechnet then
  begin
    FErgebnis := fWert1 + fWert2;
    FBerechnet := true;
  end;
  result := FErgebnis;
end;

procedure TForm1.Button1Click(Sender: TObject);
var test: TMeineDaten;
begin
  test:=TMeineDaten.create;
  test.Wert1:=strtoint(edit1.text);
  test.Wert2:=strtoint(edit2.text);
  label1.caption:=inttostr(test.ergebnis);
  test.Free;
end;

end.
Erstmal die Frage ob das so OOP Konform durchgeht? Und dann hätte ich da noch eine Frage zur Eingabe-Exeptionbehandlung. Was wäre OOP Konform günstiger,
die Exeptionbehandlung in die Klasse zu integrieren (im Setter) oder wie hier gehabt in einer Controlprocedure der VCL?

Ich hätte die Exeptionbehandlung numal gerne komplett in der Klasse. So wie ich es jetzt mache, kann ich jedoch im Setter nicht prüfen, ob ein leeres
Editfeld vorliegt. Delphi schmeist zwar eine Econvert Error Exeption wegen dem strtoint, jedoch hätte ich gerne eigene Exeptions und dann alle
Bedingungsabfragen in der Klasse. Dazu müsste ich ja dem Setter ein String übergeben, die strtoint Konvertierung ausführen und dann aber einen Integer schreiben. Wäre solch eine vorgehensweise überhaupt Sinnvoll? Wie könntedafür die property Deklaration aussehen? Bei allem was ich probiert habe,
beschwert sich Delphi wegen inkompatibler Typen.

mfG newbe
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#20

Re: kleines OOP Beispiel bitte um Anmerk./Verbesserungvorsch

  Alt 15. Okt 2008, 17:05
Wichtig für dich wäre noch try..finally. Das benutzt man wie folgt:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var test: TMeineDaten;
begin
  test:=TMeineDaten.create;
  try
    test.Wert1:=strtoint(edit1.text);
    test.Wert2:=strtoint(edit2.text);
    label1.caption:=inttostr(test.ergebnis);
  finally
    test.Free; //Der Teil wird immer ausgeführt, egal ob Exception kommt oder nicht
  end;
end;
Ansonsten würdest du eine Exception werfen, das PRogramm springt raus aus deinen Methoden und du rufst nie Free auf -> Speicherloch

Exceptions solltest du immer in den unteren Klassen werfen (so wie du es in TMeineDaten gemacht hast) und in der Klasse, welche sowieso für Anzeige (GUI) zuständig ist anzeigen. Die VCL macht das ja schonmal, in dem sie spätestens am Ende der Ereignis-/Messagebehandlung einen Except-Block hat und dann mittels Application.Showexception ein Fenster bringt. Wenn du also am Exceptiontest nichts verändern willst, dann kannst du es so durchlaufen lassen ohne eigene Exceptionbehandlung (try..except).
Ansonsten kann man an dem Beispiel jetzt nicht viel mehr sagen. Ausser dass du in dem speziellen Fall anstatt inttostr auch tryintsotr nehmen kannst um Fehler gleich abzufangen bzw. eine eigene Exception zu kreieren.


Eine übliche Vorgehensweise ist auch in bestimmten Klassen die Exception abzufangen und dann gleich wieder zu werfen, aber mit einer eigenen Ergänzung:
Delphi-Quellcode:
try
 ...
except
  on e:Exception do
    raise Exception.create(e.MEssage+#13#10+'Ich will auch noch was sagen!');
end;
Und nicht zu vergessen auch mal eigene Exceptionklassen zu verwenden.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:43 Uhr.
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