[Delphi] Objecten in TObjectList casten naar interface

Pagina: 1
Acties:
  • 174 views sinds 30-01-2008
  • Reageer

  • PostbodeSiemen
  • Registratie: Maart 2000
  • Laatst online: 19-08-2024
Ik heb een class met daarin een TObjectlist om van alles in te stoppen.
Wat er in gaat implementeerd wel allemaal dezelfde interface.
Als ik nu een object uit de list trek krijg ik hem niet meer gekast naar de interface en kan ik er dus ook geen methoden op aanroepen. Wat doe ik fout?

De definitie van de observer classes en interfaces.

code:
1
2
3
   ILogObserver = interface
   TFileLogObserver = class(TInterfacedObject, ILogObserver)
   TMemoFieldLogObserver = class(TInterfacedObject, ILogObserver)


En de code van de observable.
Deze code roept bij elk object in de TObjectList de methode writeLog aan.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
   currentObservers : TObjectList;

   procedure TLogObservableAdapter.writeLog(logMessage: TLogMessage);
   var
      i, aantal: integer;
      tempObserver:   TObject;
   begin
      aantal := currentObservers.Count;
      for i := 0 to aantal - 1 do
      begin
         tempObserver := currentObservers.items[i];
         tempObserver.writeLog(logMessage);
      end;
   end;

Dit werkt dus niet omdat tempObserver een TObject is en de methode writelog niet kent.
Als tempObserver als ILogObserver declareer krijg ik hem niet uit de TObjectList omdat TObject != ILogObserver.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 10:45

Creepy

Tactical Espionage Splatterer

Uit een TObjectlist krijg je altijd een TObject. Dat TObject kan je weer omzetten (casten) naar een willekeurig ander Object. Is een cast zoals
code:
1
(tempobserver as TFileLogObserver).writelog
niet mogelijk?

Een tweede mogelijkheid is een sub-klasse maken van TObjectlist, waarin je dan de methods get en put en de property items overerft. Scheelt je bij het gebruik van de objectlist typecasting.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
TMyObjectlist = class (TObjectlist)
protected
    function get(index: integer): TMyObject;
    procedure put(index: integer; value: TMyObject);
public
   items[index: integer]: TMyObject read get write put;
end;

procedure TMyObject.put;
begin
        inherited put(index,value); //geen cast nodig.
end;

procedure TMyObject.get;
begin
       result:=inherited get(index, value); // weer geen cast nodig.
end;

Code is uit m'n hoofd, dus er zullen wel fouten inzitten.

Voor interfaces is ook vast wel zoiets mogelijk. Overigens maakt Delphi bij een Interface ook meestal een klasse. Dus bij een IDinges is meestal ook een TDinges te vinden.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • PostbodeSiemen
  • Registratie: Maart 2000
  • Laatst online: 19-08-2024
Creepy schreef op 01 augustus 2002 @ 10:53:
Is een cast zoals
code:
1
(tempobserver as TFileLogObserver).writelog
niet mogelijk?
Het probleem is dat in een lijst een TFileLogObserver, een TMemoLogObserver en nog wat andere soorten kunnen voorkomen. Je kan hem dus niet expliciet casten.
Creepy schreef op 01 augustus 2002 @ 10:53:
Een tweede mogelijkheid is een sub-klasse maken van TObjectlist, waarin je dan de methods get en put en de property items overerft. Scheelt je bij het gebruik van de objectlist typecasting.

code:
1
....

Code is uit m'n hoofd, dus er zullen wel fouten inzitten.

Voor interfaces is ook vast wel zoiets mogelijk.
Hierbij zie ik helaas ff niet in hoe dit mij gaat helpen :?
Creepy schreef op 01 augustus 2002 @ 10:53:
Overigens maakt Delphi bij een Interface ook meestal een klasse. Dus bij een IDinges is meestal ook een TDinges te vinden.
Hier zat ik dus ook ff aan te denken, ik kan natuurlijk de interface veranderen in een abstracte klasse. Dan hetgeen wat uit de list wordt gehaald daar naar toe casten. Dan weet ik alleen niet of hij nog wel weet van welke subklasse hij de methodes moet uitvoeren. En het is minder mooi. Ze hebben niet voor niks interfaces uitgevonden.

  • whoami
  • Registratie: December 2000
  • Laatst online: 13:00
Kan je geen gebruik maken van de RTTI functionaliteiten van Delphi om te bepalen hoe je moet casten?

En kan je geen gebruik maken van de polymorphing eigenschappen van Delphi?
Als je nu het volgende hebt:
code:
1
2
3
4
5
6
7
8
9
10
11
var
  MyList : TObjectList;  // bevat objecten van het type TObject.
  MyObject  : TMyObject; // is afgeleid van een basisobject dat inherit van TObject;
  ThObject  : TThObject; // is afgeleid van datzelfde basisobject
begin
  MyObject := TMyObject.Create();
  MyList.Add (MyObject);
  ThObject := TThObject.Create();
  MyList.Add (ThObject);
  TBaseObject(MyList.Objects[0]).CallFunction();
end;

Dan cast je de objecten in uw TObjectList naar de class vanwaar je de andere objecten hebt afgeleid en dat moet dan toch werken als je die methode 'Callfunction' in het gemeenschappelijke basisobject definieert en in de classes TMyObject en TThObject overidded?

Sorry als het een beetje wazig overkomt, ben nog niet goed wakker.

edit:
nog ietskes vergeten.
:)

https://fgheysels.github.io/


  • PostbodeSiemen
  • Registratie: Maart 2000
  • Laatst online: 19-08-2024
whoami schreef op 01 augustus 2002 @ 11:22:

code:
1
2
3
4
5
6
7
8
9
10
11
var
  MyList : TObjectList;  // bevat objecten van het type TObject.
  MyObject  : TMyObject; // is afgeleid van een basisobject dat inherit van TObject;
  ThObject  : TThObject; // is afgeleid van datzelfde basisobject
begin
  MyObject := TMyObject.Create();
  MyList.Add (MyObject);
  ThObject := TThObject.Create();
  MyList.Add (ThObject);
  TBaseObject(MyList.Objects[0]).CallFunction();
end;
Dit bedoelde ik ook als laatste in mijn mailtje er boven.
In plaats van een aantal klassen die 1 interface implementeren heb ik dan een aantal klassen die van dezelfde afgeleid zijn.
Het enige nare is dat b.v. mijn TMemoLogObserver al van een TMemo is afgeleid en Delphi volgens mij geen multiple inheritance ondersteund.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 10:45

Creepy

Tactical Espionage Splatterer

Waarom dan niet
code:
1
2
3
TBaseLogObjserver = class(TInterfacedObject, ILogObserver);
TFileLogObserver = class (TBaseLogObserver);
TMemoFieldLogObserver = class (TBaseLogObserver);

Kan je alles omcasten naar een TBaseLogObjserver die wel die method heeft. En met betrekking tot die objectlist, als je daar dan een list van maakt die een TBaseLogObserver teruggeeft, hoed je niet meer te casten

code:
1
2
for k:=0 to currentObservers.items.count - 1 do
    currentObservers.items[i].writelog


En als je bij de definitie van je items er default; achter zet is currentObservers[i].writelog ook mogelijk

[edit]En ja.. Delphi houd zelf bij welke subklasse hij moet hebben, aangezien van elk Object bekend is van welke klasse hij is (zie de property classname).

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

Waarom gebruik je objecten en interfaces door elkaar?

Je hebt ook een TInterfaceList; en je kunt een objecten naar interfaces casten...

  • PostbodeSiemen
  • Registratie: Maart 2000
  • Laatst online: 19-08-2024
Verwijderd schreef op 01 augustus 2002 @ 11:49:
Je hebt ook een TInterfaceList
|:( |:( |:( |:(

Zat er ook eigenlijk wel in. Heb nog niks geprobeerd maar volgens mij gaat dat mijn leven vergemakkelijken.

  • PostbodeSiemen
  • Registratie: Maart 2000
  • Laatst online: 19-08-2024
AAAAARRRGGGHHHHHH!!!!!!!

Die delphi componenten doen ook echt NOOIT wat ik wil dat ze doen.
:(

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Wat is er dan? lijkt me duidelijk dat je een TInterfaceList nodig hebt

We adore chaos because we like to restore order - M.C. Escher


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

En anders kan je het met je TObjectList or whatever laten werken met Supports(...) ipv as. Maar dan moet je wel al je interfaces een GUID geven, anders gaat Supports niet werken

var Test: ITest;
begin
if Supports(ObjList.Items[0], ITest, Test) then

Houd er ook rekening mee dat zodra je er een I(nterface) van gemaakt hebt en die gaat out of scope, dat ie dan het object vanzelf Freed. Extra _AddRef toevegen helpt in zulke gevallen.

We adore chaos because we like to restore order - M.C. Escher


  • Monga
  • Registratie: Mei 2002
  • Laatst online: 09:51
Er bestaat ook zoiets als
code:
1
 Var is Class
waarmee je kan testen of een Object van een bepaalde klasse is (werkt geloof ik ook met Interfaces), en
code:
1
Var.InheritsFrom(Class)
om te kijken of het een instantie van dezelfde klasse dan wel een subklasse is van Class.

Misschien dat dat helpt ;)

  • whoami
  • Registratie: December 2000
  • Laatst online: 13:00
RTTI dus. ;)

https://fgheysels.github.io/


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

InheritsFrom en is maken geen gebruik van RTTI. Er wort bij is/as (die InheritsFrom aanroepen) alleen gekeken of de VMT overeen komt.

We adore chaos because we like to restore order - M.C. Escher


  • whoami
  • Registratie: December 2000
  • Laatst online: 13:00
LordLarry schreef op 02 augustus 2002 @ 09:06:
InheritsFrom en is maken geen gebruik van RTTI. Er wort bij is/as (die InheritsFrom aanroepen) alleen gekeken of de VMT overeen komt.
Hoezo?
Met behulp van de is operator kan je toch nagaan van welk type/class een bepaald object is? Dat is dan toch run-time type information, RTTI dus?
Wat versta jij anders onder RTTI of, wat is 'echte' RTTI dan ?

https://fgheysels.github.io/


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

whoami schreef op 03 augustus 2002 @ 01:54:
[...]

Hoezo?
Met behulp van de is operator kan je toch nagaan van welk type/class een bepaald object is? Dat is dan toch run-time type information, RTTI dus?
Wat versta jij anders onder RTTI of, wat is 'echte' RTTI dan ?
Uit de Help:

RTTI allows an application to query the fields and properties of an object dynamically and to locate its methods. RTTI is used to access the values of properties when saving and loading form files, to display properties in the Object Inspector, and to associate specific methods (called event handlers) with specific properties (called events).

Dus vandaar dat ik denk dan as/is daar niet onder valt. In mijn ogen is echte RTTI het getten, setten en ontdekken van properties runtime. Maar misschien heb ik het mis :) Eingelijk maakt het ook niet zoveel uit ook.

We adore chaos because we like to restore order - M.C. Escher

Pagina: 1