Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Klasse nach Vergleich mit Feld in Klasse erzeugen (https://www.delphipraxis.net/167365-klasse-nach-vergleich-mit-feld-klasse-erzeugen.html)

ChEeTaH 26. Mär 2012 14:54

Delphi-Version: XE2

Klasse nach Vergleich mit Feld in Klasse erzeugen
 
Hallo,

ich habe mehrere Klassen, die von einer abstrakten Klasse geerbt haben.
Ich muss nun je nach Eingabewert unterscheiden, welche dieser Childklassen erzeugt werden und mit dem Ergebnis arbeiten. Ob diese Klasse das Ergebnis verarbeiten kann steht in der Klasse als Eigenschaft.
Ich habe hier versucht, zumindest teiwleise das Strategie Pattern umzusetzen.
Codebeispiel:
Delphi-Quellcode:
type TParentClass = class
  {iwas}
end;

type TChildclass(TParentclass)
  eineZahl: Integer;
  procedure eineMethode(asd: String);
end;

procedure choose;
var
 EineChildclass: TChildclass;
begin
  If eineChildclass.eineZahl = 1 then
  begin
  EineChildclass := TChildclass.Create;
  EineChildclass.eineMethode('test';
 
  // WIe frage ich ab, welche Klasse erzeugt werden muss?
  end;
end;
Ich habe etwas von Methodenklassen gelesen, wäre dies der WEg zu Ziel, oder gibt es andere Lösungen?

DeddyH 26. Mär 2012 15:12

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
Ich weiß nicht, ob es nur mir so geht, aber ich verstehe weder die Frage noch Deinen Code so richtig. Wie kannst Du ein Feld einer Instanz abfragen, die Du im Anschluss erst erzeugst?

ChEeTaH 26. Mär 2012 15:48

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
Das genau ist ja der Knackpunkt. Ich möchte die Eigenschaft gerne in der Klasse kapseln, muss aber auch wissen, welche klasse ich nun genau benutzen muss. Der vergleiswert ist variabel, deswegen dieser umständliche weg.

Bummi 26. Mär 2012 16:17

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
Suchst Du eine Class Function eineZahl ??

DeddyH 26. Mär 2012 16:26

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
RTTI? Ich verstehe immer noch nicht ganz, was eigentlich die Anforderung ist, sry.

Bummi 26. Mär 2012 16:39

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
ich vermute er such so etwas
Delphi-Quellcode:
unit Unit2;

interface

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

type

  TMasterClass=Class
    Class Function WasKannich:Integer;virtual;
  End;

  TMasterChildClass1=Class(TMasterClass)
    Class Function WasKannich:Integer;override;
  End;
  TMasterChildClass2=Class(TMasterClass)
    Class Function WasKannich:Integer;override;
  End;
  TMasterClassClass=Class of TMasterClass ;

  TForm2 = class(TForm)
    Button1: TButton;
    Image1: TImage;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
var
  CK:TMasterClassClass;
begin

    if TMasterChildClass1.WasKannich=2 then CK := TMasterChildClass1
    else if TMasterChildClass2.WasKannich=2 then CK := TMasterChildClass2;
    With CK.Create do
      begin
        Showmessage(IntToStr(WasKannich));
        Free;
      end;

end;

{ TMasterChildClass2 }

class function TMasterChildClass2.WasKannich: Integer;
begin
  Result := 2;
end;

{ TMasterChildClass1 }

class function TMasterChildClass1.WasKannich: Integer;
begin
  Result := 1;
end;

{ TMasterClass }

class function TMasterClass.WasKannich: Integer;
begin
   Result := 0;
end;

end.

shmia 26. Mär 2012 16:43

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
1.) die Basisklasse hat eine statische Methoden (in Delphi Klassenmethode genannt)
mit der man Abfragen kann ob eine Klasse bestimmte Eigenschaften hat bzw. über bestimmte Features verfügt.

2.) die Klassenmethode sollte virtuell sein; das bietet noch mehr Möglichkeiten
Delphi-Quellcode:
type
TParentClass = class
public
  class function HasFeature(const name:string):boolean;virtual;
end;

TChildclass = class(TParentclass)
  class function HasFeature(const name:string):boolean;override;
end;

class function TChildclass.HasFeature(const name:string):boolean;
begin
   // die konkrete Klasse unterstützt die Features Secure und Hip
   result := (name='Secure') or (name='hip');
end;
3.) eine Factorymethode erzeugt aufgrund der gewünschten Features ein Objekt einer konkreten (Child-)Klasse:

Delphi-Quellcode:
function TMyFactory.CreateObject(const feature:string):TParentClass;
begin
  if TChildclass1.HasFeature(feature) then
    result := TChildclass1.Create
  else if TChildclass2.HasFeature(feature) then
    result := TChildclass2.Create
  ...
  else
     result := nil;
end;
Man kann auch mehrere Features prüfen um die passende Klasse zu finden.
Anstatt jede einzelne Klasse zu testen kann man auch alle registrierten Klassen in einer Schleife testen (aber dazu benötigt man fortgeschrittene Techniken, die ich im Moment nicht erklären möchte)

PS: der Bummi war natürlich mal wieder schneller

Bummi 26. Mär 2012 16:46

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
@shmia

tschuldigkeit :oops: sonst schlägt mich immer DeddyH ....

ChEeTaH 26. Mär 2012 16:53

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
Ja genau das habe ich gesucht. Danke an alle für die schnelle Hilfe :)

himitsu 26. Mär 2012 16:54

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
Mit der neuen erweiterten RTTI kann man auch Attribute anlegen und auslesen, zu den Klassentypen (quasi ähnlich der virtuellen Klassenmethoden).

DeddyH 26. Mär 2012 16:57

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
Ja eben, nach einem Blick auf sein Profil fiel mir auch gleich RTTI ein, da muss man dann nicht soviel selbst machen.

Blup 26. Mär 2012 16:57

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
Im Prinzip muss die Factory die zu erzeugenden Klassen nicht einmal konkret kennen.
So kann man später beliebige Unterklassen ableiten, ohne TParentClass zu ändern:
Delphi-Quellcode:
unit UnitParentClass;

interface

uses
  Classes, Contnrs, SysUtils;

type
  TChildClassParams = record
    {...}
  end;

  TParentClass = class;
  TChildClassType = class of TParentClass;

  TParentClass = class
  private
    class var
      FClassList: TClassList;
    class procedure FreeList;
  protected
    class procedure Register(AClassType: TChildClassType);
    class function New(AParams: TChildClassParams; var AInstance: TParentClass): Boolean; virtual; abstract;
  public
    class function CreateInstance(AParams: TChildClassParams): TParentClass;
  end;

implementation

{ TParentClass }

class function TParentClass.CreateInstance(AParams: TChildClassParams): TParentClass;
var
  p: Pointer;
begin
  Result := nil;
  if Assigned(FClassList) then
  begin
    for p in FClassList do
    begin
      if TChildClassType(p).New(AParams, Result) then
        Exit;
    end;
  end;
end;

class procedure TParentClass.FreeList;
begin
  FreeAndNil(FClassList);
end;

class procedure TParentClass.Register(AClassType: TChildClassType);
begin
  if not Assigned(FClassList) then
    FClassList := TClassList.Create;

  FClassList.Add(AClassType);
end;

initialization

finalization
  TParentClass.FreeList;

end.
Delphi-Quellcode:
unit UnitChildClass;

interface

uses
  UnitParentClass;

type
  TChildClass = class(TParentClass)
  protected
    class function New(AParams: TChildClassParams; var AInstance: TParentClass): Boolean; override;
  end;

implementation

{ TChildClass }

class function TChildClass.New(AParams: TChildClassParams;
  var AInstance: TParentClass): Boolean;
begin
  Result := {AParams = ???} True;
  if Result then
    AInstance := Self.Create;
end;

initialization
  TChildClass.Register(TChildClass);

end.

ChEeTaH 26. Mär 2012 17:55

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
Zitat:

Zitat von shmia (Beitrag 1158702)
Anstatt jede einzelne Klasse zu testen kann man auch alle registrierten Klassen in einer Schleife testen (aber dazu benötigt man fortgeschrittene Techniken, die ich im Moment nicht erklären möchte)

Genau das würde mich interessieren. Ich habe bis jetzt eine TObjectList implementiert, wenn man das ohne manuelles einfügen der Objekte in die TObjectList lösen kann wäre das sehr praktisch.

himitsu 26. Mär 2012 18:15

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
Du kannst deine Klassen bei einer generischen
Delphi-Quellcode:
TList<TChildClassType>
registrieren und dann diese durchsuchen.

Man könnte auch z.B. ein
Delphi-Quellcode:
TDictionary<string, TChildClassType>
nutzen, wo dann der der "Schlüssel" nicht in der Klasse steht, sondern in der Liste.
Dort würde dann eine einzige Suchanfrage an diese Liste sofort die Klasse liefern.

shmia 26. Mär 2012 18:21

AW: Klasse nach Vergleich mit Feld in Klasse erzeugen
 
Zitat:

Zitat von ChEeTaH (Beitrag 1158725)
Zitat:

Zitat von shmia (Beitrag 1158702)
Anstatt jede einzelne Klasse zu testen kann man auch alle registrierten Klassen in einer Schleife testen (aber dazu benötigt man fortgeschrittene Techniken, die ich im Moment nicht erklären möchte)

Genau das würde mich interessieren.

Das ist genau das, was Blup im Beitrag #12 gezeigt hat.
Jede Child-Klasse muss zunächst registriert werden.
Er hat dann aber einen etwas indirekten Weg über die virtuelle Methode New eingeschlagen um ein Objekt einer bestimmten Klasse zu erzeugen.
Der Standardweg wäre aber einen virtuellen Konstruktor in der Basisklasse einzuführen, der dann in allen Child-Klassen überschrieben werden muss.

So macht es z.B. die VCL mit der Klasse TComponent.
Der Konstruktor ist virtuell damit zur Laufzeit immer der richtige Code ausgeführt wird.
Die hat aber zur Konsequenz dass es nur noch einen Konstruktor geben darf.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:29 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