Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Klasse mit Oberfläche verheiraten (https://www.delphipraxis.net/211088-klasse-mit-oberflaeche-verheiraten.html)

fisipjm 26. Jul 2022 16:54

AW: Klasse mit Oberfläche verheiraten
 
Junge Junge, ich hab in der letzten Stunde wieder mehr gelernt als gefühlt im ganzen letzten Jahr :lol:

Danke für die Mega Beispiele.
Packed Records... vorher nie gehört... macht aber durchaus Sinn:oops:
Danke für das TObjectlist Beispiel.
Danke für den Hinweis mit der TControllist, die wird es auf jeden Fall werden.

Kann mir nochmal jemand mit den CallBacks auf die Sprünge helfen?
Die Anzeige der Daten würde ich in die OnBeforePaint Methode der Controllist packen, aber woher weis dann die View das es jetzt was neues in der Klasse gibt wenn ich ein Add mache. Das hab ich noch nicht so ganz und irgendwie find auch auch keine eingängigen Beispiele für CallBacks bzw. Events.... Kann auch gut sein das ich falsch suche :?::pale:

KodeZwerg 26. Jul 2022 17:31

AW: Klasse mit Oberfläche verheiraten
 
hab mein oldschool schnippsel vervollständigt, zwar nur hier im editor getippst, sollte aber hoffentlich funktionieren falls erwünscht.

KodeZwerg 26. Jul 2022 19:33

AW: Klasse mit Oberfläche verheiraten
 
Zitat:

Zitat von fisipjm (Beitrag 1509336)
aber woher weis dann die View das es jetzt was neues in der Klasse gibt wenn ich ein Add mache.

Indem man ein Event erstellt was gefeuert wird.
Beispiel mit meinem Schnippsel nun auch mit Delphi getestet ( zumindest das Event :D )
Delphi-Quellcode:
unit Unit25;

interface

uses
  System.Classes;

type
  THouse = packed record
    FHeight: double;
    FLength: double;
    FName: string;
    FID: integer;
  end;
  THouses = array of THouse;

 TOnAddEvent = procedure(const Sender: TObject; const AHouse: THouse) of object;
 THouseClass = class(TObject)
   strict private
     FHouses: THouses;        // interne verwaltung
     FIndex: Integer;         // interne verwaltung
     FCount: Integer;         // interne verwaltung
     FOnAddEvent: TOnAddEvent; // interne verwaltung
   private
     procedure SetHouse(const AHouse: THouse); // schreibe das index element
     function GetHouse: THouse;                // hole das index element hervor
     procedure SetIndex(const AIndex: Integer); // versuche gewünschten index zu setzen
   public
     constructor Create;                                                                              // um die interne verwaltung zu initialisieren
     procedure Add(const AHeight, ALength: Double; const AName: string; const AID: Integer); overload; // haupt methode zum simplen adden
     procedure Add(const AHouse: THouse); overload;                                                   // neben methode die intern die haupt methode aufruft
     procedure Remove;                                                                                // löscht aktuellen index vom array
   public
     property Houses: THouses read FHouses write FHouses;                // direkter zugriff aufs interne array (ich würde es entfernen)
     property House: THouse read GetHouse write SetHouse;                // zugriff auf ein element basierend vom index
     property Index: Integer read FIndex write SetIndex;                 // steuerung für einzel array zugriffe
     property Count: Integer read FCount;                                // sagt wieviel elemente wir haben
     property OnAddEvent: TOnAddEvent read FOnAddEvent write FOnAddEvent; // feuert ein Event
   end;

implementation

constructor THouseClass.Create;
begin
  inherited Create;
  FOnAddEvent := nil;
  FIndex := -1;
  FCount := 0;
end;

procedure THouseClass.SetHouse(const AHouse: THouse);
begin
  if ((FIndex > -1) and (FIndex < FCount)) then
    FHouses[FIndex] := AHouse;
end;

function THouseClass.GetHouse: THouse;
begin
  if ((FIndex > -1) and (FIndex < FCount)) then
    Result := FHouses[FIndex];
end;

procedure THouseClass.SetIndex(const AIndex: Integer);
begin
  if ((AIndex > -1) and (AIndex < FCount)) then
    FIndex := AIndex;
end;

procedure THouseClass.Add(const AHeight, ALength: Double; const AName: string; const AID: Integer);
var
  i: Integer;
begin
  i := Length(FHouses);
  SetLength(FHouses, i + 1);
  FHouses[i].FHeight := AHeight;
  FHouses[i].FLength := ALength;
  FHouses[i].FName := AName;
  FHouses[i].FID := AID;
  FIndex := i;
  FCount := Length(FHouses);
  if Assigned(FOnAddEvent) then
    FOnAddEvent(Self, FHouses[i]);
end;

procedure THouseClass.Add(const AHouse: THouse);
begin
  Self.Add(AHouse.FHeight, AHouse.FLength, AHouse.FName, AHouse.FID);
end;

procedure THouseClass.Remove;
begin
  if ((FIndex > -1) and (FIndex < FCount)) then
    begin
      Delete(FHouses, FIndex, 1);
      FCount := Length(FHouses);
      if FIndex >= FCount then
        FIndex := Pred(FIndex);
    end;
end;

end.
und ein Demo Projekt:
Delphi-Quellcode:
unit Unit24;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  unit25;

type
  TForm24 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    FHouses: THouseClass;
    procedure OnAddEvent(const Sender: TObject; const AHouse: THouse);
  public
    { Public declarations }
  end;

var
  Form24: TForm24;

implementation

{$R *.dfm}

procedure TForm24.Button1Click(Sender: TObject);
begin
  FHouses.Add(0.0, 0.0, 'Test', 0);
end;

procedure TForm24.OnAddEvent(const Sender: TObject; const AHouse: THouse);
begin
  Memo1.Lines.Add(AHouse.FName);
end;

procedure TForm24.FormCreate(Sender: TObject);
begin
  FHouses := THouseClass.Create;
  FHouses.OnAddEvent := OnAddEvent;
end;

end.

Uwe Raabe 26. Jul 2022 20:16

AW: Klasse mit Oberfläche verheiraten
 
Zitat:

Zitat von KodeZwerg (Beitrag 1509347)
Zitat:

Zitat von fisipjm (Beitrag 1509336)
aber woher weis dann die View das es jetzt was neues in der Klasse gibt wenn ich ein Add mache.

Indem man ein Event erstellt was gefeuert wird.

Genau! Im Falle einer TObjectList gibt es das schon: OnNotify

fisipjm 27. Jul 2022 07:01

AW: Klasse mit Oberfläche verheiraten
 
Guten Morgen,

nach einem Käffchen und einer guten Mütze Schlaf, macht auch alles wieder mehr Sinn. Man sollte ja meinen, nach einigen Jahren sollte man die Basics beherrschen...:oops:

Danke, für die Beispiele, dass macht absolut Sinn und hilft mir endlich das Eventhandling besser zu verstehen. Ich werde wahrscheinlich die Variante von KodeZwerg nehmen. Glaube da lerne ich noch ein bisschen mehr, als bei der vorgefertigen TObjectlist. Für zukünftige Projekte wirds dann wahrscheinlich, der einfachheit wegen, die TObjectlist werden. Beim nächsten Refactoring werde ich mich wahrscheinlich für die Entscheidung schlagen wollen, aber damit muss mein Zukunfts-Ich wohl klar kommen :twisted:

Ich hätte noch 2 Fragen:
- Warum machst du die Getter und Setter in den private Bereich und die Felder in den strict private?
- Ich habe den Zugriff auf Houses nicht mit getter / setter geregelt, sondern auch über den direkten. Gibt es einen speziellen Grund das du es mit getter/Setter gelöst hast? Oder ist das einfach eine Geschmackssache?

Bei deiner Variante wäre der Zugriff ja so:

Delphi-Quellcode:
MyHouses.Index := 1;
HouseLength := MyHouses.Houses.length;
In meinem Fall
Delphi-Quellcode:
HouseLength := MyHouses.Houses[1].length;
Eine Zeile weniger :)

Grüße
PJM

Edit: Hab grad gesehen dass du beides in deinem Code implementiert hast.

KodeZwerg 27. Jul 2022 11:14

AW: Klasse mit Oberfläche verheiraten
 
Zitat:

Zitat von fisipjm (Beitrag 1509351)
1. Warum machst du die Getter und Setter in den private Bereich und die Felder in den strict private?
2. Ich habe den Zugriff auf Houses nicht mit getter / setter geregelt, sondern auch über den direkten. Gibt es einen speziellen Grund das du es mit getter/Setter gelöst hast? Oder ist das einfach eine Geschmackssache?

1. Weil getter und setter nur innerhalb der Klasse und Unit anwendbar sein sollten, im strict private kommt generell meine "interne Verwaltung", wenn die von außerhalb beschädigt wird geht meine erdachte Logik flöten.

2. Angeboten sind beide Varianten aber um Deine Frage zu beantworten, wenn ich den direkten Zugriff aufs interne array wegnehme lebt diese Klasse nun mal von den get/set :D
(So das man wie gewohnt per "for i := 0 to Pred(Klasse.Count) do" etwas machen könnte)


Ich habe es nicht zu 100% getestet, das alles ist nur hier im Editor entworfen worden, lediglich das Event habe ich getestet!


Viel Spass damit und gern geschehen :thumb:

KodeZwerg 27. Jul 2022 11:41

AW: Klasse mit Oberfläche verheiraten
 
Zitat:

Zitat von fisipjm (Beitrag 1509351)
Bei deiner Variante wäre der Zugriff ja so:

Delphi-Quellcode:
MyHouses.Index := 1;
HouseLength := MyHouses.Houses.length;
In meinem Fall
Delphi-Quellcode:
HouseLength := MyHouses.Houses[1].length;
Eine Zeile weniger :)

Erdacht war es so:
Delphi-Quellcode:
Klasse.Index := gültige Zahl
Variable := Klasse.House.Feld;


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

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