[delphi] Een static methode overriden

Pagina: 1
Acties:

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 15-05 14:44

_Thanatos_

Ja, en kaal

Topicstarter
Ik weet dat het onmogelijk is om dit te doen, en ik weet dat als een delphi programmeur ziet dat ik dit wil doen, hij gelijk zal gaan roepen dat de methode in de ancestor class virtual moet zijn. Dat dus ff terzijde, nu de praktijk:

Ik heb een class afgeleid van TCustomImageList, en ik moet wat functionaliteit in (o.a.) de Add methode toevoegen. Maar de Add methode is static, dat is een probleem, want die is dus niet te overriden. Ik weet dat het niet erg is als je een variabele van het type van mijn afgeleide class hebt en daarop de methode aanroept, maar als bijvoorbeeld een ActionList de methode aanroept, zal ie op de ancestor class aangeroepen worden omdat ie niet virtual is en dus niet overridden.

Maar tóch moet het. Dus ik dacht, goh, laat ik dan botweg de method pointer overschijven:
Delphi:
1
@(inherited Add) := @Add;
Maar dat slikt ie niet, ook deze:
Delphi:
1
@Add := @_Add;
Die slikt ie ook niet.

Iemand suggesties?

日本!🎌


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 00:34

alienfruit

the alien you never expected

Misschien kan je wat doen met de RTTI informatie? :)

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 20:44

Creepy

Tactical Espionage Splatterer

Je kan zonder override, maar met reintroduce opnieuw de add method definieren. Zolang je de method add van de superclass niet meer gebruikt lijkt me dat een prima optie ;)

Edit: ik ben lekker wakker, bovenstaande zeg je zelf ook al..

Er is ergens een vuile hack (idd de pointer naar de static function aanpassen) om het "echt" voor elkaar te krijgen, maar die kan ik zo snel niet meer vinden.

[ Voor 42% gewijzigd door Creepy op 13-12-2004 22:54 ]

"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

offtopic:
Ik kan je helaas niet helpen, maar on a tangent: Dit is weer eens een mooi voorbeeld waarom het in een taal net verkeerd om is als je specifiek moet opgeven of een methode overschreven kan worden of niet. Je moet dan als klasse-schrijver alle mogelijke toepassingen en wensen van applicatieprogrammeurs in de toekomst gaan voorzien, en als je dat niet goed doet is je klasse [niet nutteloos maar] onnodig beperkt.

Het zou eigenlijk precies andersom moeten zijn: alle methoden moeten overridebaar zijn, en de klasseschrijver moet op kunnen geven wanneer een bepaalde methode niet meer overriden mag worden (`final' maken). Zoals geïmplementeerd in Eiffel en Java.

Verwijderd

Waarom niet een nieuwe methode introduceren b.v.
AddEx
kan je in die methode gewoon de oude Add aanroepen, en vervolgens je eigen code uitvoeren, niet optimaal maar wel zo handig voor het overzicht. Het toepassen van allelei hacks brengt het gevaar met zich mee dat de werking ervan niet gegarandeerd is in nieuwere versies/updates van Delphi.


misschien heb je wat meer aan 't volgende, hier wordt een oplossing aangedragen:
http://groups.google.nl/g...1_2%2540dnews%26rnum%3D12

[ Voor 31% gewijzigd door Verwijderd op 14-12-2004 00:15 ]


  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 15-05 14:44

_Thanatos_

Ja, en kaal

Topicstarter
Creepy, als je die "hack"nog ff zou kunnen opzoeken, heel graag _/-\o_

maui71, zoals ik al zei, het gaat om een imagelist, dus het introduceren van AddEx is wel heel leuk, maar die zal nooit aangeroepen worden. TCustomImageList.Add wordt aangeroepen en die moet dus overridden/vervangen/whatever worden.

OnOfBorg: je hebt helemaal gelijk, ik vind die override directive ook vies. Gelukkig hebben zowel VB.NET als C# inmiddels ook de final directive, maargoed, daar heb ik niks aan :)

日本!🎌


Verwijderd

Kun je niet de sourcecode van de VCL gebruiken en de TCustomImageList zelf aanpassen?

Niet netjes maar in de goede oude tijd van Delphi 4 waren TClientDataSets zoooooo stabiel dat wij er flink wat hacks in hebben moeten inbouwen. Je begrijpt dat dat spannende tijden waren. Elke keer als de update van Delphi kwam eerst maar eens testen of de bugs opgelost waren en welke code wij nog toe moesten voegen. Bij Delphi 5 waren de problemen wel opgelost en konden we gewoon stock code gebruiken.

Verwijderd

De VCL broncode moet je van af blijven, tenzij je ECHT NIET anders kunt (TclientDatasets waren idd. wel ECHT buggy).

Voordat we allemaal RTTI hacks gaan verzinnen, kun je geen gebruik maken van het onChange event? Deze wordt ook uitgevoerd als er iets aan de lijst toegevoegd wordt..

Overigens.. hoe kom je er bij dat je die add methode niet kunt vervangen?

Ik testte even dit:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
TMyCustImgList = class( TCustomimageList)
    private
    public
      function Add(Image, Mask: TBitmap): Integer;
  end;

[..]

function TMyCustImgList.Add(Image, Mask: TBitmap): Integer;
begin
  ShowMessage('blaat');
end;

[..]

procedure TForm1.Button1Click(Sender: TObject);
var
  oMyCustImgList: TMyCustImgList;
begin
  oMyCustImgList:=TMyCustImgList.Create(self);
  oMyCustImgList.Add(Image1.Picture.BitMap,Image1.Picture.BitMap);

end;


En dat werkte gewoon? Bij een add kreeg ik idd mijn showmessage te zien?

[ Voor 70% gewijzigd door Verwijderd op 14-12-2004 03:37 ]


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 20:44

Creepy

Tactical Espionage Splatterer

Dit werkt ook prima. Maar als een ander stuk code de TCustomImageList.Add aanroept op jou TMyCustImgList dan wordt jouw add niet aangeroepen omdat deze niet virtual is. Daarnaast kan je geen inherited add aanroepen vanuit jouw code.

De Delphi compiler geeft je nu ook een warning dat de base method add hidden is :) (en die melding kun je weer onderdrukken met reintroduce, zodat je aangeeft dat je weet dat je een static method opnieuw aanmaakt)

[ Voor 9% gewijzigd door Creepy op 14-12-2004 08:54 ]

"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


  • Sjaaky
  • Registratie: Oktober 2000
  • Laatst online: 22-04 07:04
Kan je dit niet oplossen met delegation? Dus jouw class bevat een TCustomImageList en stuurt alle methods / events / whatever door naar die interne list. Zo kun de TCustomImageList het werk laten doen, maar wel aanpassingen aan de .add methode maken. Het is wel meer werk dan met inheritance. Je zult uiteraard wel moeten aangeven dat je een ImageList implementeert.

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 15-05 14:44

_Thanatos_

Ja, en kaal

Topicstarter
De VCL aanpassen is zinloos en totaal onwenselijk, omdat het over een component gaat dat ik ga publiceren.

Het OnChange event (de dynamische methode Change dus) had ik nog niet aan gedacht. Ik wist niet eens dat dat bestond :)
Alleen het probleem daarbij is weer dat ik in de implementatie van die methode geen id heb wát er nou veranderd is. Bij Add bijvoorbeeld moet iets anders extra's gebeuren dan bij Delete.

Sjaaky, kun je een voorbeeld geven? Want ik heb geen idee wat je bedoelt ;)

[ Voor 10% gewijzigd door _Thanatos_ op 14-12-2004 11:48 ]

日本!🎌


  • Sjaaky
  • Registratie: Oktober 2000
  • Laatst online: 22-04 07:04
Ok ik ken niet delphi niet, dus de syntax zal niet helemaal kloppen.
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
TMyCustImgList
    private
      TCustomImageList customImageList;
    public
      function Add(Image, Mask: TBitmap): Integer;
      function AddIcon(Graphics: TIcon): Integer;
      ....
      ....
  end; 

function TMyCustImgList.Add(Image, Mask: TBitmap): Integer;
begin
   doSometingSpecial();
   a = customImageList.Add(Image, Mask);
   doSomeOtherThings();
   return a;
end; 

function TMyCustImgList.AddIcon(Graphics: TIcon): Integer;
begin
   return customImageList.AddIcon(Graphics);
end; 
...
...


Je maakt dus een wrapper om de TCustomImageList heen. Het is wel een hoop werk aangezien je _alle_ methoden en events etc.. zult moeten doorgeven.
Er is alleen nog wel een probleem en dat is dat je jouw klasse er ook voor de compiler uit zal moeten zien als een TCustomImageList. Dat betekent dat je moet overerven van een TCustomImageList. In dat geval bestaat je klasse uit 2 TCustomImageLists. 1tje die er is om te laten zien dat je een TCustomImageList bent en 1 die je daadwerkelijk gebruikt. Dit is alleen niet echt netjes. Maar ik ken de vcl niet van buiten (en de help vind ik ook niet echt praktisch), dus misschien is er iemand die dit eleganter kan oplossen.

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 15-05 14:44

_Thanatos_

Ja, en kaal

Topicstarter
Dat werkt niet, omdat een andere stuk code of component dat gebruikt maakt van een imagelist (en daarmee dus ook van mijn afgeleide imagelist), een echte ImgList.TCustomImageList (of afgeleide dus) verwacht, en niets anders.

[ Voor 5% gewijzigd door _Thanatos_ op 14-12-2004 12:26 ]

日本!🎌


Verwijderd

Verwijderd schreef op dinsdag 14 december 2004 @ 03:27:
De VCL broncode moet je van af blijven, tenzij je ECHT NIET anders kunt (TclientDatasets waren idd. wel ECHT buggy).
Tuurlijk, en als je componenten wilt publiseren is het helemaal onmogelijk, maar dan heeft de TS eigenlijk gewoon pech. De static pointer aanpassen heeft namelijk ook geen zin aangezien die per Delphi versie (en update) anders kan zijn.
Overigens.. hoe kom je er bij dat je die add methode niet kunt vervangen?
De TS schijnt dit te willen kunnen doen:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
TMyCustImgList = class( TCustomimageList)
    private
    public
      function Add(Image, Mask: TBitmap): Integer;
  end;

[..]

function TMyCustImgList.Add(Image, Mask: TBitmap): Integer;
begin
  ShowMessage('blaat');
end;

[..]

procedure TForm1.Button1Click(Sender: TObject);
var
  oMyImgList: TMyCustImgList ;
  oCustImgList: TCustomimageList;
begin
  oMyImgList:=TMyCustImgList .Create(self);
  oCustImgList:=(oMyImgList as TCustomimageList);
  oCustImgList.Add(Image1.Picture.BitMap,Image1.Picture.BitMap);

end;


En dan moet dus de showmessage afgaan. Succes.....

Wat eventueel zou kunnen is dat de TS van alle componenten waarvan hij wil dat die zijn Image list moeten kunnen benaderen een afgeleid component maakt dat ipv naar de TCustomImgList naar zijn eigen ImageList verwijst. Niet echt optimaal maar een gewone search & replace kan bestaande code aanpassen en voor nieuwe code kun je de aangepaste componenten gebruiken. Blijf je zitten met de 3th party componenten die de gebruikers al hebben maar dat is al een kleiner probleem.

[ Voor 20% gewijzigd door Verwijderd op 14-12-2004 13:52 ]


Verwijderd

Creepy schreef op dinsdag 14 december 2004 @ 08:53:
Dit werkt ook prima. Maar als een ander stuk code de TCustomImageList.Add aanroept op jou TMyCustImgList dan wordt jouw add niet aangeroepen omdat deze niet virtual is. Daarnaast kan je geen inherited add aanroepen vanuit jouw code.
Aargh je hebt gelijk, had even beter moeten lezen.. maar goed, dan blijft het onChange event imo een betere keuze dan RTTI hacks etc..

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 20:44

Creepy

Tactical Espionage Splatterer

Verwijderd schreef op dinsdag 14 december 2004 @ 16:48:
[...]


Aargh je hebt gelijk, had even beter moeten lezen.. maar goed, dan blijft het onChange event imo een betere keuze dan RTTI hacks etc..
Ik kan die hack overigens ook niet meer vinden.. ik dacht dat ie ergens op de community site van borland stond...

"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

Creepy schreef op dinsdag 14 december 2004 @ 17:19:
Ik kan die hack overigens ook niet meer vinden.. ik dacht dat ie ergens op de community site van borland stond...
Ik kan alleen deze tekst van Peter Below (TeamB) vinden op deja:
Nope, cannot be done. Calls to static methods are hardcoded in the generated code. So the only possible intervention would be to patch the method itself, which is not a good idea if you then need to call the old method somewhere else...

Give us more specifics about the problem you try to solve, perhaps there is an alternate solution.
In diezelfde thread staat nog wel:
Well, there is no table of pointers for the static methods of an
object since their address is well-defined at compile time, so no
resolution is necessary at runtime.

It is however possible to hack the static method itself and replace
its code with a jump instruction to another routine that has a similar
signature to the original static method.
Als ik dit goed lees, IS er geneens een RTTI hack voor..

[ Voor 4% gewijzigd door Verwijderd op 14-12-2004 17:43 ]


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 12:05

Tomatoman

Fulltime prutser

Een private method kan via een hack inderdaad overridden worden, maar dat lukt je alleen door het exacte adres van de method in de RTTI te achterhalen. Dat kan door alle methods te tellen, waarna je de RTTI kun veranderen. Deze oplossing is echter gebonden aan de versie van Delphi en is ERG vies.

Een goede grap mag vrienden kosten.


Verwijderd

tomatoman schreef op dinsdag 14 december 2004 @ 19:18:
Een private method kan via een hack inderdaad overridden worden, maar dat lukt je alleen door het exacte adres van de method in de RTTI te achterhalen. Dat kan door alle methods te tellen, waarna je de RTTI kun veranderen. Deze oplossing is echter gebonden aan de versie van Delphi en is ERG vies.
Wat ik uit de tekst van Peter Below (=BorlandTeamB) opmaak is dit niet waar. Letterlijk staat er in zijn tekst dat statische methodes hard-coded worden, oftewel niet werken met een method pointer oid. De omschrijving eronder bevestigd dit; die wil in feite de executable hacken door een .jmp ergens neer te zetten.

Ik krijg het ook niet voor elkaar, kun je eens een voorbeeld posten van hoe je dat zou willen doen?

[ Voor 9% gewijzigd door Verwijderd op 14-12-2004 20:38 ]


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 00:34

alienfruit

the alien you never expected

Peter Below is dus echt niet Borland he <g> Dat is TeamB :+
[url]Maar zoals ik al eerder had gezegt RTTI kan je misschien helpen[/url] Of je maakt gebruik van dynamic programming waartbij je dus gebruik maak van de AST van de parser, waarbij je vervolgens adres van de method opzoekt en dus je execuable gaat patchen na elke compilatie. Erg handig, als je gebruik maakt van Final Builder. Ik zal er vanavond eens over nadenken.

[ Voor 57% gewijzigd door alienfruit op 14-12-2004 20:28 ]


Verwijderd

http://info.borland.com/newsgroups/teamb/
TeamB was created more than 10 years ago as an experiment in encouraging advanced users of Borland products to answer other users' technical support questions.
[..]
Borland greatly appreciates the excellent and skilled service TeamB provides on our product newsgroups, and we hope you will too.
Je hebt gelijk dat hij geen borland is, maar hij wordt wel backed by borland, om het zo te zeggen. Op Delphi gebied is die man best een begrip..

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 00:34

alienfruit

the alien you never expected

Nou dan kan je beter dthorpe@borland.com mailen met je vraag, dat is de bouwer van de compiler. :)
Pagina: 1