Results 1 to 14 of 14

Thread: Inherited class methods

  1. #1
    Delphi & OO in Vlaanderen SamWitse's Avatar
    Join Date
    Sep 2007
    Location
    Brussel
    Posts
    833

    Question Inherited class methods

    Beste Delphinauten,


    Ik wil een inherited class property maken.
    - Een class property maken in de Master
    - Een lokale getter in de de Master, want een getter moet static zijn.
    - Een abstracte class procedure, die opgeroepen wordt door de getter.
    - Een implementatie in de van de class procedure in de Child.

    Het schrijven en compileren lukt.
    Het uitvoeren geeft een abstract error bij het oproepen van de class procedure in de getter.

    Wat mis ik?
    Bestaan er andere wegen om een overerfbare polymorfe class property te maken?

    PHP Code:
    unit Unit1;
    interface
    type  TMaster = class
      private
        class function 
    GetMasterIdinteger; static; {MOET een static method zijn om als getter voor een property te dienen}
      protected
        class function 
    GetChildIDintegervirtual; abstract;
      public
        class 
    property idinteger read GetMasterId ;
      
    end;

      
    TChild = class(TMaster)
      protected
        class function 
    GetChildIDintegeroverride;
      
    end;

    implementation
    TMaster }
    class function 
    TMaster.GetMasterIdinteger;
    begin
      result 
    := GetChildID ;   { <= hier geeft hij een abstract error}
    end;

    TChild }
    class function 
    TChild.GetChildIDinteger;
    begin
      result 
    := 1
    end
    ;

    end
    Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration.

    Sam Witse.
    Delphi & OO in Vlaanderen

  2. #2
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,708
    TChild is afgeleidt van TMaster en heeft een implementatie voor GetChildID, TMaster heeft geen weet van TChild, dus hij roept zijn eigen GetChildID aan, welke niet geïmplementeerd is.

    De oplossing is om in TMaster ook GetChildID te implementeren en, bijvoorbeeld, een 0-resultaat te geven.
    In alle afgeleiden (zoals TChild) kun je er vervolgens voor kiezen om de default (0-resultaat uit TMaster) te gebruiken middels "Result := inherited GetChildID" of een eigen resultaat te genereren "Result := 1";
    TMemoryLeak.Create(Nil);

  3. #3
    Werkt dat wel zo met class functions en properties???

    Dit werkt n.l. wel.
    Of heb je de id echt als class property nodig (en niet als gewone property)?

    Delphi Code:
    1. type
    2.   TMaster = class
    3.   private
    4.     function GetMasterId: integer;
    5.   protected
    6.     function GetChildID: integer; virtual; abstract;
    7.   public
    8.     property id: integer read GetMasterId;
    9.   end;
    10.  
    11.   TChild = class(TMaster)
    12.   protected
    13.     function GetChildID: integer; override;
    14.   end;
    15.  
    16.   { TMaster }
    17. function TMaster.GetMasterId: integer;
    18. begin
    19.   result := GetChildID; { <= hier geeft hij een abstract error }
    20. end;
    21.  
    22. { TChild }
    23. function TChild.GetChildID: integer;
    24. begin
    25.   result := 1
    26. end;
    27.  
    28. procedure TForm1.Button1Click(Sender: TObject);
    29. var
    30.   T: TChild;
    31. begin
    32.   T := TChild.Create;
    33.   try
    34.     Showmessage(T.id.ToString);
    35.   finally
    36.     T.Free;
    37.   end;
    38. end;

  4. #4
    Delphi & OO in Vlaanderen SamWitse's Avatar
    Join Date
    Sep 2007
    Location
    Brussel
    Posts
    833
    Ik ben net bezig om oude code te verbeteren.
    Properties die nu per object bestaan, maar die eigenlijk class properties zijn, tracht ik om te zetten.

    Dus: JA, ik heb class properties nodig
    Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration.

    Sam Witse.
    Delphi & OO in Vlaanderen

  5. #5
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,708
    Quote Originally Posted by rvk View Post
    Dit werkt n.l. wel.
    Ik denk dat Sam een TMaster gebruikt (want dan gaat het inderdaad fout):
    Delphi Code:
    1. procedure TForm1.Button1Click(Sender: TObject);
    2. var
    3.   T: TMaster;
    4. begin
    5.   T := TMaster.Create;
    6.   try
    7.     Showmessage(T.id.ToString);
    8.   finally
    9.     T.Free;
    10.   end;
    11. end;
    TMemoryLeak.Create(Nil);

  6. #6
    Delphi & OO in Vlaanderen SamWitse's Avatar
    Join Date
    Sep 2007
    Location
    Brussel
    Posts
    833
    Snel even getest.
    Het resultaat is 0.
    De inherited class function wordt dus niet opgeroepen.

    TMaster heeft geen weet van TChild
    dat is waar, maar de applicatie roept de property van Child op, dus die moet weten dat hij ook GetChildID van Child moet gebruiken, net zoals bij gewone properties, zoals Rik heeft uitgewerkt.

    De applicatie:

    procedure TForm2.Button1Click(Sender: TObject);
    var
    Child: TChild ; {Is dit zelfs nodig?}
    begin
    Edit1.Text := inttostr(TChild.id)
    end;

    Blijkbaar werkt polyformisme niet bij class methods?
    Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration.

    Sam Witse.
    Delphi & OO in Vlaanderen

  7. #7
    Delphi & OO in Vlaanderen SamWitse's Avatar
    Join Date
    Sep 2007
    Location
    Brussel
    Posts
    833
    Nope, zie mijn ander antwoord.
    Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration.

    Sam Witse.
    Delphi & OO in Vlaanderen

  8. #8
    Quote Originally Posted by VideoRipper View Post
    Ik denk dat Sam een TMaster gebruikt (want dan gaat het inderdaad fout):
    Delphi Code:
    1. procedure TForm1.Button1Click(Sender: TObject);
    2. var
    3.   T: TMaster;
    4. begin
    5.   T := TMaster.Create;
    6.   try
    7.     Showmessage(T.id.ToString);
    8.   finally
    9.     T.Free;
    10.   end;
    11. end;
    Nee hoor. Dit gaat ook fout:

    Delphi Code:
    1. type
    2.   TMaster = class
    3.   private
    4.     class function GetMasterId: integer; static; { MOET een static method zijn om als getter voor een property te dienen }
    5.   protected
    6.     class function GetChildID: integer; virtual; abstract;
    7.   public
    8.     class property id: integer read GetMasterId;
    9.   end;
    10.  
    11.   TChild = class(TMaster)
    12.   protected
    13.     class function GetChildID: integer; override;
    14.   end;
    15.  
    16.   { TMaster }
    17. class function TMaster.GetMasterId: integer;
    18. begin
    19.   result := GetChildID; { <= hier geeft hij een abstract error }
    20. end;
    21.  
    22. { TChild }
    23. class function TChild.GetChildID: integer;
    24. begin
    25.   result := 1
    26. end;
    27.  
    28. procedure TForm1.Button1Click(Sender: TObject);
    29. var
    30.   T: TChild;
    31. begin
    32.   T := TChild.Create;
    33.   try
    34.     Showmessage(T.id.ToString);
    35.   finally
    36.     T.Free;
    37.   end;
    38. end;

  9. #9
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,708
    Hmmm, ik gebruik class methods and properties heel spaarzaam en eigenlijk alleen bij singleton-achtige classes.

    Inderdaad moet/hoef je bij een class method de class niet te instantiëren en *zou* een losse ShowMessage(TChild.Id.ToString); moeten volstaan.
    TMemoryLeak.Create(Nil);

  10. #10
    Delphi & OO in Vlaanderen SamWitse's Avatar
    Join Date
    Sep 2007
    Location
    Brussel
    Posts
    833
    Inderdaad moet/hoef je bij een class method de class niet te instantiëren
    Dàt is het issue niet :-)

    Ik vermoed dat polymorfisme in class methods gewoon niet geïmplementeerd is, maar geen compiler-error geeft. Ik vind er ook niks op tinternet over.

    Class methods lijken mij nuttig om info te geven die voor elk object van deze klasse hetzelfde zijn.
    Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration.

    Sam Witse.
    Delphi & OO in Vlaanderen

  11. #11
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,708
    Dat weet ik, het was in reactie op dit:
    Quote Originally Posted by SamWitse View Post
    var
    Child: TChild ; {Is dit zelfs nodig?}
    TMemoryLeak.Create(Nil);

  12. #12
    Delphi & OO in Vlaanderen SamWitse's Avatar
    Join Date
    Sep 2007
    Location
    Brussel
    Posts
    833
    Blijkbaar is er geen oplossing:

    Eens je in de static method GetMasterId zit, is de hele inheritance verbroken, en weet Delphi niet meer wie de oproepende klasse was.

    Een oplossing die wel werkt, is enkel met een abstracte class function te werken. Hiermee kun je een read-only class property vervangen.

    Delphi Code:
    1. unit Unit1;
    2.  
    3. interface
    4.  
    5. type
    6.   TMaster = class
    7.   public
    8.     class function ID: integer; virtual; abstract;
    9.   end;
    10.  
    11.   TChild = class(TMaster)
    12.   public
    13.     class function ID: integer; override;
    14.   end;
    15.  
    16. implementation
    17.  
    18. { TChild }
    19.  
    20. class function TChild.ID: integer;
    21. begin
    22.   result := 1
    23. end;
    24.  
    25. end.

    Een virtuele class knuffel voor wie een inheritable class property kan maken!
    Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration.

    Sam Witse.
    Delphi & OO in Vlaanderen

  13. #13
    Silly member NGLN's Avatar
    Join Date
    Aug 2004
    Location
    Werkendam
    Posts
    5,133
    Inderdaad niet mogelijk. Uit de help over Properties:
    ... Class property accessors must themselves be declared as class static methods, or class fields. ...
    (Sender as TNLDUser).Signature := 'Groeten van Albert';

  14. #14
    Senior Member Thaddy's Avatar
    Join Date
    Dec 2004
    Location
    Amsterdam
    Posts
    2,211
    Quote Originally Posted by SamWitse View Post
    Blijkbaar is er geen oplossing:

    Eens je in de static method GetMasterId zit, is de hele inheritance verbroken, en weet Delphi niet meer wie de oproepende klasse was.

    Een oplossing die wel werkt, is enkel met een abstracte class function te werken. Hiermee kun je een read-only class property vervangen.

    Delphi Code:
    1. unit Unit1;
    2.  
    3. interface
    4.  
    5. type
    6.   TMaster = class
    7.   public
    8.     class function ID: integer; virtual; abstract;
    9.   end;
    10.  
    11.   TChild = class(TMaster)
    12.   public
    13.     class function ID: integer; override;
    14.   end;
    15.  
    16. implementation
    17.  
    18. { TChild }
    19.  
    20. class function TChild.ID: integer;
    21. begin
    22.   result := 1
    23. end;
    24.  
    25. end.

    Een virtuele class knuffel voor wie een inheritable class property kan maken!
    Wel, het kan, een beetje, als de static procedure/function een parameter als var declareert, die een instance vertegenwoordigd.
    Je hebt een instance nodig. Anders dan dit weet ik het niet te doen, maar dit werkt/ zou moeten werken.
    In FPC werkt het. Ik gebruik Delphi veel te weinig sinds ik niet meer hoef te werken.
    De wijze waarop ik redeneer is dat er anders geen Self is.
    Last edited by Thaddy; 30-Jan-22 at 11:07. Reason: Geen
    Werken aan Ansi support voor Windows is verspilde tijd, behalve voor historici.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •