![]() |
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 07:28 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