Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Record-Variable in Klasseninstanz setzen (https://www.delphipraxis.net/172028-record-variable-klasseninstanz-setzen.html)

Uwe Raabe 9. Dez 2012 22:36

AW: Record-Variable in Klasseninstanz setzen
 
Zitat:

Zitat von Perlsau (Beitrag 1194873)
Zitat:

Zitat von Uwe Raabe (Beitrag 1194868)
Zitat:

Zitat von Perlsau (Beitrag 1194835)
Außerdem würden, wenn deine Vermutung zuträfe, auch die anderen Proceduren wie z.B. Set_StatusBar, die ja funktionieren, eine Zugriffsverletzung auslösen.

Nicht zwingend! Solange diese Methoden keine Felder der Instanz ansprechen, funktionieren die auch wenn die Instanz nicht initialisiert ist. (Wobei man sich dann aber fragen muss, warum sie nicht als Klassenmethoden realisiert sind bzw. überhaupt zu der Klasse gehören.)

Set_StatusBar gehört zur Klasse TMain_Zugriff, wie du im ersten Code-Fenster meines ersten Postings leicht feststellen kannst ...

Ich hatte nichts anderes behauptet. Es ist nur so, daß eine (nicht virtuelle) Methode einer Klasse nur dann eine initialisierte Instanz der Klasse benötigt, wenn sie auch auf Felder der Instanz zugreift. Würde die Methode z.B. lediglich ein MessageBeep aufrufen, dann funktioniert das auch wenn kein Create aufgerufen wurde. Die Tatsache, daß der Aufruf einer Methode einer Instanz funktioniert, heißt nicht zwingend, daß die Instanz initialisiert ist. Das kann man erst wissen, wenn man die Implementation der Methode kennt.

Übrigens: ein recht bekanntes Beispiel ist die Methode Free, die man auch aufrufen kann, wenn die entsprechende Instanzvariable nil ist.

Sir Rufo 9. Dez 2012 23:34

AW: Record-Variable in Klasseninstanz setzen
 
Zum Testen:
Delphi-Quellcode:
type
  TFoo = class
  private
    FData : string;
    function GetData : string;
  public
    property Data : string read GetData;
  end;

function TFoo.GetData : string;
begin
  if Self = nil then
    Result := 'keine Instanz vorhanden'
  else
    Result := FData;
end;

procedure Test;
var
  LFoo : TFoo;
begin
  ShowMessage( LFoo.Data );
end;

sx2008 10. Dez 2012 02:09

AW: Record-Variable in Klasseninstanz setzen
 
Mann ist das ein Kuddelmuddel in dem Sourcecode!
Ich versuche mal Ordnung zu schaffen.
Wir beginnen mit dem Record:
Delphi-Quellcode:
TTab_User = RECORD
  Titel_Index : Integer;
  Titel_SortIndex : Integer;
  Titel_SortOrder : Boolean;
  Titel_SortText : String;
END;
und stellen die wichtigste Frage:
Könnte es nicht sein, dass TTab_User nicht eine Klasse statt einen Records sein sollte?
Eine Klasse ist im Prinzip ein Record + Methoden.

Antwort: Ja, es gibt potentielle Methoden für die Klasse TTab_User:
Delphi-Quellcode:
// Filmtitel - Initialisierung von User_Tab
DatMod.User_Tab.Titel_Index := DatMod.Aset_UserTabs.FieldByName('Titel_Index').AsInteger;
DatMod.User_Tab.Titel_SortIndex := DatMod.Aset_UserTabs.FieldByName('Titel_SortIndex').AsInteger;
DatMod.User_Tab.Titel_SortOrder := NOT DatMod.Aset_UserTabs.FieldByName('Titel_SortOrder').AsBoolean;
DatMod.User_Tab.Titel_SortText := DatMod.Aset_UserTabs.FieldByName('Titel_SortText').AsString;
Und damit sieht die Klasse im 1. Entwurf so aus:
Delphi-Quellcode:
TTab_User = class(TObject)
public
  TitelIndex : Integer;
  SortIndex : Integer;
  SortOrder : Boolean;
  SortText : String;

  procedure LoadFromDataset(ds:TDataset);
  procedure SaveToDataset(ds:TDataset);
  procedure Clear;
END;

procedure TTab_User.LoadFromDataset(ds:TDataset);
begin
  TitelIndex:= ds.FieldByName('Titel_Index').AsInteger;
  SortIndex := ds.FieldByName('Titel_SortIndex').AsInteger;
  SortOrder := NOT ds.FieldByName('Titel_SortOrder').AsBoolean;
  SortText := ds.FieldByName('Titel_SortText').AsString;
end;
Der Anfang ist gemacht.
Die weiteren Schritte sehen so aus:
* aus den public Variablen werden Properties gemacht
* weitere Methoden (z.B. procedure Clear oder SaveToDataset)entdecken und zur Klasse hinzufügen
* überprüfen ob die Klasse vollständig ist (gibt es noch weitere Felder aus der Tabelle "User_Tab"?)
* den Sourcecode der Klasse in eine eigene Unit verschieben
* Ein Objekt der neuen Klasse TTab_User in die Klasse TMain_Zugriff einbauen
* überlegen ob ein Objekt von TTab_User ausreicht oder ob man nicht eine Liste von diesen Objekten braucht
* müssen TTab_User-Objekte kopiert werden können? Fall ja, von TPersistent ableiten und die Methode Assign überschreiben

Uwe Raabe 10. Dez 2012 08:47

AW: Record-Variable in Klasseninstanz setzen
 
Zitat:

Zitat von Sir Rufo (Beitrag 1194886)
Zum Testen:
Delphi-Quellcode:
type
  TFoo = class
  private
    FData : string;
    function GetData : string;
  public
    property Data : string read GetData;
  end;

function TFoo.GetData : string;
begin
  if Self = nil then
    Result := 'keine Instanz vorhanden'
  else
    Result := FData;
end;

procedure Test;
var
  LFoo : TFoo;
begin
  ShowMessage( LFoo.Data );
end;

Das war aber auch ein bisschen Glück! Bei lokalen Variablen innerhalb Prozeduren und Funktionen kann man nicht sicher sein, daß eine Klasseninstanz immer nil ist. Deswegen wird der Aufruf von Test auch bei einigen zu einer Schutzverletzung führen.

Hier mal ein bisschen mehr zum Spielen:

Delphi-Quellcode:
type
  TFoo = class
  private class var
    FCount: Integer;
  private
    FData : string;
    class constructor Create;
    function GetData : string;
  public
    constructor Create;
    property Data : string read GetData;
  end;

constructor TFoo.Create;
begin
  inherited;
  Inc(FCount);
  FData := 'Instanz: ' + IntToStr(FCount);
end;

class constructor TFoo.Create;
begin
  FCount := 0;
end;

function TFoo.GetData : string;
begin
  if Self = nil then
    Result := 'keine Instanz vorhanden'
  else
    Result := FData;
end;

procedure Test(init, nilit: Boolean);
var
  LFoo : TFoo;
begin
  if init then
    LFoo := TFoo.Create
  else if nilit then
    LFoo := nil;
  ShowMessage( LFoo.Data );
end;

begin
  Test(false, true);
  Test(true, false);
  Test(false, false);
end.
Der Class-Constructor könnte zur Zeit noch entfallen, da der Compiler auch Klassen-Variablen initialisiert, aber das muss ja nicht immer so bleiben.

Elvis 10. Dez 2012 14:32

AW: Record-Variable in Klasseninstanz setzen
 
Zitat:

Zitat von sx2008 (Beitrag 1194887)
Mann ist das ein Kuddelmuddel in dem Sourcecode!
Ich versuche mal Ordnung zu schaffen.

Das geht mir schon so seit ich den Thread das erste Mal sah.
Das kann doch kein Mensch lesen. (Lesen ist was anderes als "mit Mühe Entziffern" :!:)


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:16 Uhr.
Seite 2 von 2     12   

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