![]() |
unterschiedliche Klassen variabel instanzieren
Guten Morgen... :hi:
es ist wahrscheinlich einfacher als gedacht aber ich quäle mich schon seit gestern durch die DP Suche ohne wirklich die Frage beantwortet zu bekommen. Ziel: - Klasse Test wird erzeugt mit Übergabeparameter - Klasse Test erzeugt Klasse entsprechend dem Übergabeparameter als Property Beispiel: bei 1 --- Klasse Test1 bei 2 --- Klasse Test2 . . . den Übergabeparameter wollte ich über eine Case Struktur auswerten und entsprechend erzeugen. Da müßte die Varable ja erst in im case deklariert werden... was ja nicht geht. Ob Klasse Test1 von Test abgeleitet ist oder eigenständig ist mir relativ egal. Bitte helft mir in die Richtung... Danke :hi: |
AW: unterschiedliche Klassen variabel instanzieren
Ich seh jetzt gerade das Problem nicht, sry :cyclops:
Und warum müsste eine Variable erst im Case deklariert werden? |
AW: unterschiedliche Klassen variabel instanzieren
Das warum ist mir auch noch etas unklar,
aber es stimmt. Ob wohl ein Objekt eigentlich auch "nur" ein Record mit Zeiger ist, funktioniert Case dort nicht, allerdings
Delphi-Quellcode:
TImageListLoader = class
data: record case boolean of false: (); true: (); end; end; |
AW: unterschiedliche Klassen variabel instanzieren
Moin. Ich weiß nicht es was für dich ist aber ich habe mir mal ein Konstrukt gebaut wo ich dynamisch, variabel gewählte Klasse, erzeugt habe.
Ich habe das so gelöst. (etwas einfacher hier) Die Klasse TAction bekommt eine Klassenreferenz übergeben und erzeugt sich daraus ein Objekt.
Delphi-Quellcode:
gruß
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TBase = class(TObject) public procedure Action; virtual; abstract; end; TSpecial1 = class(TBase) public procedure Action; override; end; TSpecial2 = class(TBase) public procedure Action; override; end; TBaseClass = class of TBase; TAction = class(TObject) public constructor Create(aClass: TBaseClass); end; TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} procedure TSpecial1.Action; begin showmessage('Action 1'); end; procedure TSpecial2.Action; begin showmessage('Action 2'); end; constructor TAction.Create(aClass: TBaseClass); var c : TBase; begin c := aClass.Create; c.Action; c.Free; end; procedure TForm1.Button1Click(Sender: TObject); begin TAction.Create(TSpecial1); end; procedure TForm1.Button2Click(Sender: TObject); begin TAction.Create(TSpecial2); end; end. Sebastian |
AW: unterschiedliche Klassen variabel instanzieren
Danke für Eure Antworten...
ich kann mich im Moment leider nicht damit beschäftigen und näher darauf eingehen... Es gibt Dinge die (leider) wichtiger sind. Ich melde mich wenn ich die Zeit gefunden habe. :hi: |
AW: unterschiedliche Klassen variabel instanzieren
öhm, wasn das für ne MemoryLeakMaschine?
Code:
procedure TForm1.Button2Click(Sender: TObject);
begin TAction.Create(TSpecial2); end; |
AW: unterschiedliche Klassen variabel instanzieren
Zitat:
Denke dem geneigten Entwickler wäre es aufgefallen bzw. nutzt den code eh etwas umfangreicher. ..
Code:
procedure TForm1.Button2Click(Sender: TObject);
var a:TAction; begin a := TAction.Create(TSpecial2); a.free; end; |
AW: unterschiedliche Klassen variabel instanzieren
Man könnte die Klassen auch von TComponent ableiten und die Form als Owner mitgeben ... dann räumt die Form auf.
Oder :oops:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
begin TAction.Create(TSpecial2).Free; end; |
AW: unterschiedliche Klassen variabel instanzieren
Und wenn wir schon wieder so kleinlich sind, dann fehlt im Konstruktor von TAction ein Try-finally-Block:
Delphi-Quellcode:
:stupid:
constructor TAction.Create(aClass: TBaseClass);
var c : TBase; begin c := aClass.Create; try c.Action; // Könnte ja eine Exception auswerfen ... finally c.Free; end; end; |
AW: unterschiedliche Klassen variabel instanzieren
Hmmm... Die Eingangsfrage beschäftigt sich mit einer Classfactory, wenn ich nicht irre.
Und nun wird klein-klein über unwichtige Dinge philosophiert. So ein Resourcenschutzblock ist ja ganz nett, aber im allgemeinen überflüssig wie ein Kropf. Ausnahmen sind knappe Resourcen (z.B. von Windows), die in einer unteren Schicht angefordert und auch im Fehlerfall wieder freigegeben werden müssen. Dann kümmert sich jedoch (z.B.) ein Securitymanager um die Exception. Bei einem Buttonklick kann man natürlich auch einen Resourcenschutzblock anwenden, aber wozu? Wenn's knallt, kann ich sowieso noch nicht ausliefern... |
AW: unterschiedliche Klassen variabel instanzieren
Nochmal danke an alle... 8-)
ich habe mal versucht die obigen Tipps umzusetzen. Im Moment habe ich entnervt aufgegeben. Ich denke langsam über eine Designumstellung nach, da ich glaube was ich vorhabe geht nicht. Ich erkläre mein Ziel noch mal anders. - ich benötige eine Variable die die Instanz eines Objektes enthällt - je nach Wert eines Integer soll das entsprechende Objekt in der Variable abgelegt werden - die Objekte sind zwar von einer Basis abgeleitet haben aber unterschiedliche Properties etc. Normalerweise wird ja die Variable mit der Klasse deklariert. Nur wie deklariere ich die wenn nicht klar ist welches Objekt da mal rein soll ? Damit kann ich auch nicht auf die Properties zugreifen. Wo ist der Denkfehler ? |
AW: unterschiedliche Klassen variabel instanzieren
Meinst du so ?
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TKlasse = class(TObject) public constructor Create(const ATyp: integer); overload; constructor Create; overload; end; TKlasse1 = class(TKlasse) function MachWas: string; end; TKlasse2 = class(TKlasse) function MachWas: string; end; TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Machwas(const ATyp:integer); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin Machwas(1); end; procedure TForm1.Button2Click(Sender: TObject); begin Machwas(2); end; procedure TForm1.Machwas(const ATyp:integer); var Klasse: TKlasse; begin if ATyp=1 then begin Klasse:=TKlasse.Create(ATyp); try with Klasse as TKlasse1 do ShowMessage(Machwas); finally Klasse.Free; end; end; if ATyp=2 then begin Klasse:=TKlasse.Create(ATyp); try with Klasse as TKlasse2 do ShowMessage(Machwas); finally Klasse.Free; end; end; end; constructor TKlasse.Create; begin inherited Create; end; constructor TKlasse.Create(const ATyp: integer); begin if ATyp=1 then Self:= TKlasse1.Create; if ATyp=2 then Self:= TKlasse2.Create; end; function TKlasse1.MachWas: string; begin Result:= 'TKlasse1.MachWas'; end; function TKlasse2.MachWas: string; begin Result:= 'TKlasse2.MachWas'; end; end. |
AW: unterschiedliche Klassen variabel instanzieren
Falls Dir das etwas hilft, ich caste in meiner Klasse auf unterschiedliche Property-Klassen.
Sieh Dir mal Data_Create.. und Data_Is... an. In "Data" können unterschiedliche Objekte verwaltet werden. Die Unit wird von einem Experten erstellt. Die Regionen enthalten die automatisch erzeugten Quelltextabschnitte. Bei der Verfahrensweise müssen halt für alle möglichen Klassen entsprechende Methoden eingerichtet werden (in meinem Fall macht der Experte das allerdings autiomatisch). In der Anwendung funktioniert das tadellos.
Delphi-Quellcode:
unit odTournament;
interface uses Classes, SysUtils, od, odOlympicCustom, gOlympic, odPerson, odCourt {$REGION 'USES'}, odMelee, odSwiss, odGroup, odKo, odGroupKo{$ENDREGION 'USES'}; type TodTournament = class(TodOlympicCustom) private {$REGION ' PRIVAT'} {$REGION ' name'} FName: String; {$ENDREGION ' name'} {$REGION ' activate'} FActivate: Boolean; {$ENDREGION ' activate'} {$REGION ' excludecourts'} FExcludeCourts: String; {$ENDREGION ' excludecourts'} {$REGION ' data'} FData: Tod; {$ENDREGION ' data'} {$ENDREGION ' PRIVAT'} protected {$REGION ' PROTECTED'} {$REGION ' name'} function get_Name: String; virtual; procedure set_Name(const Value: String); virtual; {$ENDREGION ' name'} {$REGION ' activate'} function get_Activate: Boolean; virtual; procedure set_Activate(const Value: Boolean); virtual; {$ENDREGION ' activate'} {$REGION ' excludecourts'} function get_ExcludeCourts: String; virtual; procedure set_ExcludeCourts(const Value: String); virtual; {$ENDREGION ' excludecourts'} {$ENDREGION ' PROTECTED'} public constructor Create(AOwner: TComponent); override; destructor Destroy; override; function ExistPerson(odPerson: TodPerson): Boolean; function GetFreeCourtForTournament(DoubleFlag: Boolean): TodCourt; function TournamentTypeName: String; {$REGION ' PUBLIC'} {$REGION ' data_Melee'} procedure Data_Create_Melee; procedure Data_Free_Melee; function Data_Is_Melee: Boolean; function Melee: TodMelee; {$ENDREGION ' data_Melee'} {$REGION ' data_Swiss'} procedure Data_Create_Swiss; procedure Data_Free_Swiss; function Data_Is_Swiss: Boolean; function Swiss: TodSwiss; {$ENDREGION ' data_Swiss'} {$REGION ' data_Group'} procedure Data_Create_Group; procedure Data_Free_Group; function Data_Is_Group: Boolean; function Group: TodGroup; {$ENDREGION ' data_Group'} {$REGION ' data_Ko'} procedure Data_Create_Ko; procedure Data_Free_Ko; function Data_Is_Ko: Boolean; function Ko: TodKo; {$ENDREGION ' data_Ko'} {$REGION ' data_GroupKo'} procedure Data_Create_GroupKo; procedure Data_Free_GroupKo; function Data_Is_GroupKo: Boolean; function GroupKo: TodGroupKo; {$ENDREGION ' data_GroupKo'} {$REGION ' name'} [AttrOd] property Name: String read get_Name write set_Name; {$ENDREGION ' name'} {$REGION ' activate'} [AttrOd] property Activate: Boolean read get_Activate write set_Activate; {$ENDREGION ' activate'} {$REGION ' excludecourts'} [AttrOd] property ExcludeCourts: String read get_ExcludeCourts write set_ExcludeCourts; {$ENDREGION ' excludecourts'} {$REGION ' data'} [AttrOd] property Data: Tod read FData; {$ENDREGION ' data'} {$ENDREGION ' PUBLIC'} published end; implementation uses pOlympic, odTournamentEvent; // TodTournament constructor TodTournament.Create(AOwner: TComponent); begin inherited; {$REGION ' CREATE'} {$REGION ' data'} FData := nil; {$ENDREGION ' data'} {$ENDREGION ' CREATE'} end; destructor TodTournament.Destroy; begin inherited; end; function TodTournament.ExistPerson(odPerson: TodPerson): Boolean; begin if Data_Is_Melee then Result := Melee.ExistPerson(odPerson) else Result := False; end; function TodTournament.GetFreeCourtForTournament(DoubleFlag: Boolean): TodCourt; var I: Integer; C: TodCourt; te: TodTournamentEvent; begin Result := nil; te := OwnerTournamentEvent(Self); for I := 0 to te.Place.CountCourts - 1 do begin C := te.Place.Court(I); if (C.IsFree) and (not CourtInTournament(Self, C.odId)) and ((not DoubleFlag) or (C.CourtType <> ctSingle)) then Exit(C); end; end; function TodTournament.TournamentTypeName: String; begin Result := Data.odClass; if Result = 'Melee' then Result := 'Melee' else if Result = 'Swiss' then Result := 'Schweizer' else if Result = 'Group' then Result := 'Gruppen' else if Result = 'Ko' then Result := 'KO'; end; {$REGION 'GETTER+SETTER'} {$REGION 'data_Melee'} procedure TodTournament.Data_Create_Melee; begin Data_Free_Melee; FData := TodMelee.Create(Self); FData.OdName := 'Data'; end; procedure TodTournament.Data_Free_Melee; begin FreeAndNil(FData); end; function TodTournament.Data_Is_Melee: Boolean; begin Result := (Assigned(FData)) and (FData is TodMelee); end; function TodTournament.Melee: TodMelee; begin if Data_Is_Melee then Result := (FData as TodMelee) else Result := nil; end; {$ENDREGION 'data_Melee'} {$REGION 'data_Swiss'} procedure TodTournament.Data_Create_Swiss; begin Data_Free_Swiss; FData := TodSwiss.Create(Self); FData.OdName := 'Data'; end; procedure TodTournament.Data_Free_Swiss; begin FreeAndNil(FData); end; function TodTournament.Data_Is_Swiss: Boolean; begin Result := (Assigned(FData)) and (FData is TodSwiss); end; function TodTournament.Swiss: TodSwiss; begin if Data_Is_Swiss then Result := (FData as TodSwiss) else Result := nil; end; {$ENDREGION 'data_Swiss'} {$REGION 'data_Group'} procedure TodTournament.Data_Create_Group; begin Data_Free_Group; FData := TodGroup.Create(Self); FData.OdName := 'Data'; end; procedure TodTournament.Data_Free_Group; begin FreeAndNil(FData); end; function TodTournament.Data_Is_Group: Boolean; begin Result := (Assigned(FData)) and (FData is TodGroup); end; function TodTournament.Group: TodGroup; begin if Data_Is_Group then Result := (FData as TodGroup) else Result := nil; end; {$ENDREGION 'data_Group'} {$REGION 'data_Ko'} procedure TodTournament.Data_Create_Ko; begin Data_Free_Ko; FData := TodKo.Create(Self); FData.OdName := 'Data'; end; procedure TodTournament.Data_Free_Ko; begin FreeAndNil(FData); end; function TodTournament.Data_Is_Ko: Boolean; begin Result := (Assigned(FData)) and (FData is TodKo); end; function TodTournament.Ko: TodKo; begin if Data_Is_Ko then Result := (FData as TodKo) else Result := nil; end; {$ENDREGION 'data_Ko'} {$REGION 'data_GroupKo'} procedure TodTournament.Data_Create_GroupKo; begin Data_Free_GroupKo; FData := TodGroupKo.Create(Self); FData.OdName := 'Data'; end; procedure TodTournament.Data_Free_GroupKo; begin FreeAndNil(FData); end; function TodTournament.Data_Is_GroupKo: Boolean; begin Result := (Assigned(FData)) and (FData is TodGroupKo); end; function TodTournament.GroupKo: TodGroupKo; begin if Data_Is_GroupKo then Result := (FData as TodGroupKo) else Result := nil; end; {$ENDREGION 'data_GroupKo'} {$REGION 'name'} function TodTournament.get_Name: String; begin Result := FName; end; procedure TodTournament.set_Name(const Value: String); begin if FName <> Value then begin FName := Value; Changed; end; end; {$ENDREGION 'name'} {$REGION 'activate'} function TodTournament.get_Activate: Boolean; begin Result := FActivate; end; procedure TodTournament.set_Activate(const Value: Boolean); begin if FActivate <> Value then begin FActivate := Value; Changed; end; end; {$ENDREGION 'activate'} {$REGION 'excludecourts'} function TodTournament.get_ExcludeCourts: String; begin Result := FExcludeCourts; end; procedure TodTournament.set_ExcludeCourts(const Value: String); begin if FExcludeCourts <> Value then begin FExcludeCourts := Value; Changed; end; end; {$ENDREGION 'excludecourts'} {$ENDREGION 'GETTER+SETTER'} initialization RegisterClasses([TodTournament]); end. |
AW: unterschiedliche Klassen variabel instanzieren
Zitat:
Sondern sowas:
Delphi-Quellcode:
Viel besser, denn die Basisklasse wird nicht mehr angefasst. Du kannst Dir auch eine allgemeine Classfactory bauen, die in einer TClasslist (wozu gibt es die wohl?) je nach ATyp den entsprechenden Eintrag liefert.
Type
TKlasseClassFactory = Class Class Function CreateKlasse (ATyp : Integer) : TKlasse; End; Class Function TKlasseClassFactory.CreateKlasse (ATyp : Integer) : TKlasse; Begin Case ATyp Of 1 : Result := TKlasse1.Create; 2 : Result := TKlasse2.Create; End; Normalerweise ist ein 'case' Konstrukt ein indiz für schlechtes OOP, denn in einer Methode werden -je nach Wert- unterschiedliche Aktionen ausgelöst. Hier ist das jedoch erlaubt. Ich würde übrigens aus dem 'ATYP' einen Enumerationswert machen oder zumindest die 'magic numbers' 1 und 2 als Konstante deklarieren. |
AW: unterschiedliche Klassen variabel instanzieren
Zitat:
Delphi-Quellcode:
Damit ist diese Bedingung erfüllt.
var
o: TObject; Soll das ein Varparameter oder ein Rückgabewert sein? Zitat:
Wird das Object erst erzeugt oder nur ausgewählt? Du hast nicht mal klargestellt, ob du überhaupt eine Factory bauen willst.
Delphi-Quellcode:
case i of
1: o := TKatze.Create; 2: o := TAuto.Create; {...} Zitat:
Man kann nur nicht direkt auf o.Scheinwerfer zugreifen, auch wenn es sich um ein Auto handelt. Dazu muss man erst auf die richtige Klasse casten oder ein Interface abfragen. Wenn dein Problem nicht so einfach gelöst werden kann, existieren weitere Bedingungen, die du aber nicht formuliert hast. Die meisten scheinen hier einfach nur zu raten, was du eigentlich erreichen willst. |
AW: unterschiedliche Klassen variabel instanzieren
Zitat:
|
AW: unterschiedliche Klassen variabel instanzieren
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:20 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