AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Instanz einer Klasse identifizieren?!

Ein Thema von maddin4u · begonnen am 2. Feb 2006 · letzter Beitrag vom 8. Feb 2006
Antwort Antwort
Seite 1 von 2  1 2      
maddin4u

Registriert seit: 24. Mär 2004
38 Beiträge
 
#1

Instanz einer Klasse identifizieren?!

  Alt 2. Feb 2006, 15:56
Hallo

Um mein Problem/Anliegen zu erläutern werde ich dies an einem Kleinen Beispiel machen.

Ich habe die Unit "UTest.pas", in der folgende Typen-Deklaration ist:

Delphi-Quellcode:
...
type
  TTest = class
  private
  public
    Text: string;
    constructor Create(ID: integer);
  end;
...
Später im Programm habe ich zum Beispiel einen Button1 mit der OnClick-Prozedur

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  hallo: TTest;
begin
  hallo:= TTest.Create(22);
end;
Und nun möchte ich zum Beispiel auf einem 2ten ButtonClick die erzeugte Instanz "wiederfinden". Zum Beispiel:

Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
begin
  TTest[22].Text:= 'Irgendwas';
end;
Wie kann ich dies ganze bewerkstelligen ohne eine globale Variable zu verwenden. Das ganze sieht ja ganz stark nach einem Array aus, welches ich allerdings nicht global haben möchte.

Ist es irgendwie möglich ein solches Array mit in die Unit Utest.pas zu packen?

Vielen Dank!
  Mit Zitat antworten Zitat
Benutzerbild von sh17
sh17

Registriert seit: 26. Okt 2005
Ort: Radebeul
1.594 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: Instanz einer Klasse identifizieren?!

  Alt 2. Feb 2006, 17:02
Besser wäre da eine TObjectList bzw. ein spezialiserter Nachfahre dieser.

Wenn Du die Liste nur in der Unit brauchst, kannst Du sie ja lokal deklarieren.
Sven Harazim
--
  Mit Zitat antworten Zitat
kalmi01
(Gast)

n/a Beiträge
 
#3

Re: Instanz einer Klasse identifizieren?!

  Alt 2. Feb 2006, 17:29
Hi,

wie kommt denn die "22" zustande ?
Zählst Du bei jedem Button1Click weiter ?
Willst Du die jeweils letzte Instanz haben ?

Nach welchen Kriterien soll den Button2Click die Instanz auswählen ?
  Mit Zitat antworten Zitat
maddin4u

Registriert seit: 24. Mär 2004
38 Beiträge
 
#4

Re: Instanz einer Klasse identifizieren?!

  Alt 2. Feb 2006, 20:35
Sorry, ich habe vergessen dies zu kommentieren.

Die 22 ist einfach ne Beliebige ID. Das heisst jede Instanz soll am besten mit einer ID versehen werden an der man die Klasse dann identifizieren kann.

Zum Beispiel könnte ich mir auch sowas vorstellen:

  TTest[22].Text = 'blub' Ich weiß allerdings nicht ob das geht.

Ich werde mir auch nochmal TObjectList anschauen, eventuell bekomme ich es damit hin ...
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#5

Re: Instanz einer Klasse identifizieren?!

  Alt 2. Feb 2006, 21:23
Hi,
wenn du wirklich gänzlich auf globale Variablen verzichten möchtest, kannst du eine Kapselung bauen, die dir Instanzen liefert. Ich weiß nicht in wie weit du mit dem Factory-Pattern vertraut bist, aber etwas in der Art kann dir hier schon sehr gut weiterhelfen.

Erstelle einfach eine Klasse, die alle Objekte von deinem Typen verwaltet. (hier könntest du dann auch automatische IDs vergeben). Jedenfalls definierst du hier auch eine Methode, die dir eine Instanz liefert (und diese Instanz speichert, ob im Array oder in einer Liste ist dann deine Sache). Über genau diese kannst du dann auch alle Instanzen finden (die deine persönlichen Bedingungen erfüllen). Ok, weicht damit schon stark vom eigentlichen Sinn des Factory-Pattern ab, aber das wäre eine andere Sache.

Gruß Der Unwissende
  Mit Zitat antworten Zitat
Benutzerbild von sh17
sh17

Registriert seit: 26. Okt 2005
Ort: Radebeul
1.594 Beiträge
 
Delphi 11 Alexandria
 
#6

Re: Instanz einer Klasse identifizieren?!

  Alt 3. Feb 2006, 05:43
Das Factory-Pattern wollte ich ihm auch vorschlagen, nur das endet letztendlich mit der beschriebenen Erweiterung des patterns auch in einer globalen Variable. Wo soll die Faktory sonst die Objekte verwalten?

Hier mal ein Beispiel einer typisierten ObjectList mit Erweiterung:

Delphi-Quellcode:
  TTest = class
  private
    ID : Integer;
  public
    Text: string;
    constructor Create(_ID: integer);
  end;

  TTestObjectList = class(TObjectList)
  protected
    function GetItem(Index: Integer): TTest;
    procedure SetItem(Index: Integer; AItem: TTest);
  public
    function Add(AItem: TTest): Integer;
    function Extract(Item: TTest): TTest;
    function Remove(AItem: TTest): Integer;
    function IndexOf(AItem: TTest): Integer;
    procedure Insert(Index: Integer; AItem: TTest);
    function First: TTest;
    function Last: TTest;
    property Items[Index: Integer]: TTest read GetItem write SetItem; default;

    function GetItemById(_ID : Integer; _CreateIfNotExists : Boolean = true) : TTest;
  end;


{ TTest }

constructor TTest.Create(_ID: integer);
begin
  ID := _ID;
end;

{ TTestObjectList }

function TTestObjectList.Add(AItem: TTest): Integer;
begin Result := inherited Add(AItem); end;

function TTestObjectList.Extract(Item: TTest): TTest;
begin Result := TTest(inherited Extract(Item)); end;

function TTestObjectList.First: TTest;
begin Result := TTest(inherited First); end;

function TTestObjectList.GetItem(Index: Integer): TTest;
begin Result := TTest(inherited Items[Index]); end;

function TTestObjectList.IndexOf(AItem: TTest): Integer;
begin Result := inherited IndexOf(AItem); end;

procedure TTestObjectList.Insert(Index: Integer; AItem: TTest);
begin inherited Insert(Index, AItem); end;

function TTestObjectList.Last: TTest;
begin Result := TTest(inherited Last); end;

procedure TTestObjectList.SetItem(Index: Integer; AItem: TTest);
begin inherited Items[Index] := AItem; end;

function TTestObjectList.Remove(AItem: TTest): Integer;
begin Result := inherited Remove(AItem);end;


function TTestObjectList.GetItemById(_ID: Integer;
  _CreateIfNotExists: Boolean): TTest;
var
  i : Integer;
begin
  Result := nil;
  for i := 0 to Count-1 do
  if Items[i].ID = _ID then
  begin
    Result := Items[i];
    exit;
  end;

  if not _CreateIfNotExists then exit;

  Result := TTest.Create(_ID);
  Add(Result);
end;
Sven Harazim
--
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#7

Re: Instanz einer Klasse identifizieren?!

  Alt 3. Feb 2006, 07:14
willst du nur keine Globale nehmen oder auch nix im Private/Public/Protected definieren? Und was spricht dagegen das am private/public/protected zu definieren, dafür sind die Bereiche doch da. Ganz richtig wäre es natürlich wenn du eine Liste baust welche die instanzen verwaltet dann musst du diese Liste aber auch im Private/Public/Protected halten.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#8

Re: Instanz einer Klasse identifizieren?!

  Alt 3. Feb 2006, 07:30
Eine einfache Implementation einer prozessbezogenen statischen Klassenvariablen mit automatischer Generierung von IDs (warum sollte der Benutzer der Klasse diese generieren müssen...) könnte so aussehen:
Delphi-Quellcode:
{ interface }

type
  TFooInstanceID = Integer;
  TFoo = class
  private
    FInstanceID: TFooInstanceID;
  public
    constructor Create(); virtual;
    property InstanceID: TFooInstanceID read FInstanceID;
  end;

{ implementation }

var
  // Prozessbezogene statische Klassenvariable von TFoo
  _FooInstanceID: TFooInstanceID; // = 0

constructor TFoo.Create();
begin
  inherited Create();
  FInstanceID := InterlockedIncrement(_FooInstanceID);
end;
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#9

Re: Instanz einer Klasse identifizieren?!

  Alt 3. Feb 2006, 09:45
Ok, statische Klassenvariablen gibt es ja eigentlich nicht in Delphi. Natürlich ist deine Variable, die du hier hochzählst wiederum global und das lässt sich (wie hier schon gesagt wurde) einfach vermeiden.

Was ich meinte noch mal als Delphi Code
Delphi-Quellcode:
type
  TFoo = class(TObject)
    private
      FId : Cardinal;
      ...
    public
      constructor create(const Id : Cardinal);
      property Id : Cardinal read FId;
  end;

constructor TFoo.Create(const Id : Cardinal);
begin
  inherited create;
  self.Id := Id;
end;
Delphi-Quellcode:
type
  TFooFactory = class(TObject)
    private
      id : Cardinal;
      InstanceList : TFooList;
    public
      constructor create;
      destructor destroy; override;
      function getFooInstance : TFoo;
  end;

constructor TFooFactory.Create;
begin
  inherited create;
  self.id := 0;
  self.InstanceList := TFooList.Create;
end;

destructor TFooFactory.Destroy;
begin
  self.InstanceList.Free; // Achtung, hier müssen natürlich auch alle gespeicherten Instanzen aut. gelöscht werden
  inherited destroy;
end;

function TFooFactory.getFooInstance : TFoo;
var buffer : TFoo;
begin
  buffer := TFoo.Create(self.id);
  inc(self.id);
  self.InstanceList.Add(buffer);
end;
Wie man sieht, kann man also sehr leicht eine Liste im Private Bereich verwalten und imho gehört sie auch genau dahin. Dies ist natürlich ein stark vereinfachtes Beispiel, aber es kann sehr leicht angepasst werden, so dass man dann die TFooList nur noch nach einem speziellen TFoo durchsucht.

Gruß Der Unwissende

[Edit]
Ach ja, wenn man die Nummern alle nur einmal vergeben möchte, übergreifend für mehr als einen möglichen Aufrufer, sollte man natürlich etwas threadsafe arbeiten. Ansonsten natürlich auch noch ein Singleton-Pattern auf die Factory anwenden, dann gibt es nur eine Instanz von dieser TFooFactory, die man bekommt und somit hat man dort auch wieder eine globale Eindeutigkeit der Ids. Allerdings kommt man beim Singleton Pattern (soviel ich weiß) nicht mehr um eine globale Variable herum.
[/Edit]
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#10

Re: Instanz einer Klasse identifizieren?!

  Alt 3. Feb 2006, 10:18
Zitat von Der_Unwissende:
Allerdings kommt man beim Singleton Pattern (soviel ich weiß) nicht mehr um eine globale Variable herum.
Wird zwar eine sehr theoretische Diskussion; aber ich habe nichts gegen globale Variablen. Die Verwaltung und Sichtbarkeit sollte allerdings klar geregelt sein.
Nehmen wir zum Beispiel die GetInstance() einer möglichen Singleton-Implementation:
Delphi-Quellcode:
class function TFoo.GetInstance(): TFoo;
{$WRITEABLECONST ON}
const
  InstanceLock: Integer = Ord(False);
  Instance: TFoo = nil;
{$WRITEABLECONST OFF}
begin
  Result := Instance;
  if not Assigned(Result) then
  begin
    // Wait until lock is available
    while InterlockedExchange(InstanceLock, Ord(True)) = Ord(True) do
      Sleep(0);
    try
      // Create Instance if needed
      if not Assigned(Instance) then
        Instance := TFoo.Create();
      Result := Instance;
    finally
      // Release the lock
      InterlockedExchange(InstanceLock, Ord(False));
    end;
  end;
end;
Durch die Ausnutzung von {$WRITEABLECONST} sind die globalen Variablen nur innerhalb der Funktion sichtbar (und können nicht 'versehentlich' von 'außen' modifiziert werden).
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 21: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