pyscripter 689 Posted February 12, 2022 (edited) I tried to do something like class Test protected class function GetValue: string; virtual; public class property Value: string read GetValue; end; and I got a compiler error message stating the class property read specifier has to be either a class var or a static class method. Any idea about the reason for this restriction? Edited February 12, 2022 by pyscripter Share this post Link to post
Attila Kovacs 629 Posted February 12, 2022 because there is no instance of anything? Share this post Link to post
Uwe Raabe 2057 Posted February 12, 2022 Class properties are static and thus cannot have virtual getters or setters. That is because static members have no information about the actual class they are called on. They only know the class they are declared in. Share this post Link to post
pyscripter 689 Posted February 12, 2022 (edited) 3 hours ago, Uwe Raabe said: Class properties are static You access class properties through a class or an instance reference. That reference could be passed to a virtual class getter. Why do they have to be static? This is my question. A related question. How do virtual class methods work? Is there an equivalent to VMT for classes? By the way this works correctly: class Test protected class function GetValue: string; virtual; public property Value: string read GetValue; end; i.e. a normal property with a virtual class getter Edited February 12, 2022 by pyscripter Share this post Link to post
Attila Kovacs 629 Posted February 12, 2022 (edited) 1 hour ago, pyscripter said: You access class properties through a class or an instance reference. ok, this is weird. the "through instance reference" is just a fake, an alias to a call to the static methods. that should not exist in the language. Edited February 12, 2022 by Attila Kovacs Share this post Link to post
Uwe Raabe 2057 Posted February 12, 2022 2 hours ago, pyscripter said: Why do they have to be static? This is my question. They are static by design. The why I cannot answer. Unfortunately there is nothing we can do about it. Instead class properties you may have to switch to class functions. These can be virtual. Share this post Link to post
pyscripter 689 Posted February 12, 2022 28 minutes ago, Uwe Raabe said: They are static by design. The why I cannot answer. Unfortunately there is nothing we can do about it. This looks like an inconsistency in the language with regard to class methods and class properties. And I don't think it is documented. Share this post Link to post
Uwe Raabe 2057 Posted February 12, 2022 30 minutes ago, pyscripter said: And I don't think it is documented. I thinks it is: https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Properties_(Delphi)#Class_Properties Quote Class property accessors must themselves be declared as class static methods, or class fields. 1 Share this post Link to post
darnocian 84 Posted February 12, 2022 (edited) The issue is that for anything 'virtual' to work, a VMT needs to be available. Virtual methods are accessible on instances of a class through the class VMT. The only way to accomplish something like what you wanted would be to introduce some helper variables/procedures in delphi/pascal to accomplish this - something that is overly verbose in pascal compared to python. I've given an example below. From a python perspective, you would maybe have something like: class X: @staticmethod def do_something(): return '42' print(X.do_something()) # 42 # illustrating overriding with a lambda X.do_something = lambda: '43' print(X.do_something()) # 43 In Delphi, you could do the following: type TMyGetter = function : string; TTest = class private class var FValueGetter: TMyGetter; class function GetValue:string; public class constructor Create; class property ValueGetter: TMyGetter read FValueGetter write FValueGetter; class property Value : string read GetValue; end; function MyGetValue:string; begin exit('42'); end; function MyGetValue2:string; begin exit('43'); end; class constructor TTest.Create; begin TTest.FValueGetter := MyGetValue; end; class function TTest.GetValue:string; begin if assigned(TTest.FValueGetter) then begin result := TTest.FValueGetter(); exit; end; raise Exception.Create('no getter set'); end; begin writeln(TTest.Value); // 42 TTest.ValueGetter := MyGetValue2; writeln(TTest.Value); // 43 end. In the above the the 'ValueGetter' sort of provides the same behaviour of the VMT in allowing it to be overridden. However, this is not a polymorphic property - so inheritance does not work... child classes would essentially modify the same static variable - but this principle applies the same way for my python example above as well I think. Edited February 13, 2022 by darnocian Share this post Link to post