AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi unterschiedliche Klassen variabel instanzieren
Thema durchsuchen
Ansicht
Themen-Optionen

unterschiedliche Klassen variabel instanzieren

Ein Thema von haentschman · begonnen am 21. Jul 2011 · letzter Beitrag vom 22. Jul 2011
Antwort Antwort
Seite 2 von 2     12   
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.292 Beiträge
 
Delphi 12 Athens
 
#11

AW: unterschiedliche Klassen variabel instanzieren

  Alt 21. Jul 2011, 18:58
Nochmal danke an alle...

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 ?
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#12

AW: unterschiedliche Klassen variabel instanzieren

  Alt 21. Jul 2011, 20:57
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.
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#13

AW: unterschiedliche Klassen variabel instanzieren

  Alt 21. Jul 2011, 23:22
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 = 'Meleethen
    Result := 'Melee'
  else
  if Result = 'Swissthen
    Result := 'Schweizer'
  else
  if Result = 'Groupthen
    Result := 'Gruppen'
  else
  if Result = 'Kothen
    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.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
FredlFesl

Registriert seit: 19. Apr 2011
293 Beiträge
 
Delphi 2009 Enterprise
 
#14

AW: unterschiedliche Klassen variabel instanzieren

  Alt 22. Jul 2011, 06:26
Meinst du so ?

Delphi-Quellcode:
unit Unit1;
constructor TKlasse.Create(const ATyp: integer);
begin
  if ATyp=1 then Self:= TKlasse1.Create;
  if ATyp=2 then Self:= TKlasse2.Create;
end;
Sowas würde ich nicht machen, denn die Grundklasse muss ja dann wissen, welche Ableitungen es gibt und geben wird. Die Basisklasse muss jedesmal erweitert werden, wenn eine Ableitung hinzukommt. => Verstoß gegen Grundregeln der OOP.

Sondern sowas:
Delphi-Quellcode:
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;
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.

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.
Das Bild hängt schief.
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.429 Beiträge
 
Delphi 10.4 Sydney
 
#15

AW: unterschiedliche Klassen variabel instanzieren

  Alt 22. Jul 2011, 08:43
Zitat:
- ich benötige eine Variable die die Instanz eines Objektes enthällt
Delphi-Quellcode:
var
  o: TObject;
Damit ist diese Bedingung erfüllt.
Soll das ein Varparameter oder ein Rückgabewert sein?

Zitat:
- je nach Wert eines Integer soll das entsprechende Objekt in der Variable abgelegt werden
Ist der Integer ein Parameter oder nur intern bekannt?
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:
- die Objekte sind zwar von einer Basis abgeleitet haben aber unterschiedliche Properties etc.
Das ist eine Aussage die aber keinen Einfluß auf die anderen Bedingungen hat.
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.
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#16

AW: unterschiedliche Klassen variabel instanzieren

  Alt 22. Jul 2011, 10:15
Zitat:
Sowas würde ich nicht machen, denn die Grundklasse muss ja dann wissen, welche Ableitungen es gibt und geben wird. Die Basisklasse muss jedesmal erweitert werden, wenn eine Ableitung hinzukommt. => Verstoß gegen Grundregeln der OOP.
TE möchte in beiden Klassen verschiedene Methoden haben. TKlasse muß bei jedem Methodenaufruf geparst werden (with Klasse as TKlasse1 do ..) das ist alles. Aber ich stimme dir grundsätzlich zu, nicht sehr schön..
  Mit Zitat antworten Zitat
FredlFesl

Registriert seit: 19. Apr 2011
293 Beiträge
 
Delphi 2009 Enterprise
 
#17

AW: unterschiedliche Klassen variabel instanzieren

  Alt 22. Jul 2011, 10:59
TE möchte in beiden Klassen verschiedene Methoden haben.
Das ist manchmal so bei Ableitungen.
Das Bild hängt schief.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:34 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