David Schwartz 426 Posted February 6, 2020 What's the difference between these? TMyClass = class of TAnotherClass; TMyClass = TAnotherClass; Share this post Link to post
Guest Posted February 6, 2020 The first is a class reference (metaclass), the second is a type declaration (class). Share this post Link to post
Remy Lebeau 1398 Posted February 6, 2020 4 minutes ago, Ondrej Kelle said: the second is a type declaration (class). A declaration of an alias, anyway. TMyClass and TAnotherClass will be the same type, as far as the compiler and RTTI are concerned. Now, if you do this instead: TMyClass = type TAnotherClass; Or this: TMyClass = class(TAnotherClass) Then TMyClass will be its own unique type. Share this post Link to post
Guest Posted February 6, 2020 1 minute ago, Remy Lebeau said: A declaration of an alias, anyway. TMyClass and TAnotherClass will be the same type, as far as the compiler and RTTI are concerned. Now, if you do this instead: TMyClass = type TAnotherClass; Or this: TMyClass = class(TAnotherClass) Then TMyClass will be its own unique type. Thanks! I think you're completely right and off-topic to the question. 🙂 Share this post Link to post
David Schwartz 426 Posted February 7, 2020 hmmmm ... so we have four "variations" of this (maybe more): 1) TMyClass = TAnotherClass; 2) TMyClass = class of TAnotherClass; 3) TMyClass = type TAnotherClass; 4) TMyClass = class( TAnotherClass ); I'm familiar with (1) and (4), but (2) and (3) I've rarely seen used. In what conditions would (2) or (3) be used? Share this post Link to post
David Heffernan 2345 Posted February 7, 2020 (edited) They all do different things. Rather than have us explain this, did you read the documentation? I don't think that item 3 is very widely used. However meta classes, item 2, is widely used. Classic example is the streaming framework. It is used when you need to instantiate a class whose identity is only known at runtime. When streaming properties the framework reads the class name, looks it up using RTTI and then uses meta classes to instantiate the instance if that dynamically determined type. Always seen with virtual constructors. Edited February 7, 2020 by David Heffernan 1 Share this post Link to post
FredS 138 Posted February 7, 2020 2 hours ago, David Schwartz said: TMyClass = type TAnotherClass; This treats TPassword like a string yet in Berlin+ you can add a unique Record Helper for TPassword. TPassword = type string; // Example of a Helper for TPassword TPasswordHelper = record helper for TPassword function CheckPwdComplexity(const MinPwdLen: Word; const Level: TPwdComplexity): boolean; function ContainsLower(const Required : Cardinal = 1): boolean; function ContainsSpecial(const Required : Cardinal = 1): boolean; function ContainsUpper(const Required : Cardinal = 1): boolean; function Secure(const ProtectWith: TSecureStringProtection = ssFast): ISecureString; function BCrypt: TBCrypt; inline; end; 2 1 Share this post Link to post
Dave Nottage 557 Posted February 7, 2020 2 hours ago, David Schwartz said: but (2) and (3) I've rarely seen used (2) is used pretty extensively. In the Delphi source folder (and subfolders) there are 386 instances of it. Share this post Link to post
Fr0sT.Brutal 900 Posted February 10, 2020 Metaclasses are necessary when base Class1 is doing some things with Class2 or its descendants including creation. So you can either define virtual method CreateObj: TClass2 and override it (but that would require Class1 descendant) or just assign "class of TClass2" property. 1 Share this post Link to post
aehimself 396 Posted February 12, 2020 (edited) I personally use nr 2 really often. Imagine a simple encoder: TBaseEncoder = Class [...] TEncoderV1 = Class(TBaseEncoder) [...] TEncoderV2 = Class(TBaseEncoder) [...] TEncoderV3 = Class(TEncoderV2) [...] Basically you have a bunch of encoders, containing new methods, improvements, etc. Now let's say you want your application to be backwards compatible and be able to use previous encoders. If you add: TBaseEncoderClass = Class Of TBaseEncoder; ...and define your application as: TMyApplication = Class strict private _myencoder: TBaseEncoder; public Constructor Create(inMyEncoderClass: TBaseEncoderClass); ReIntroduce; End; Constructor TMyApplication.Create(inMyEncoderClass: TBaseEncoderClass); Begin inherited; _myencoder := inMyEncoderClass.Create; End; then you simply can call: TMyApplication.Create(TBaseEncoder); or TMyApplication.Create(TEncoderV3); to create and make your application to use the specified version of your encoder. Edited February 12, 2020 by aehimself 1 Share this post Link to post
Kryvich 165 Posted February 13, 2020 @aehimself Or using generics: TMyApplication2<T: TBaseEncoder> = class strict private _myencoder: TBaseEncoder; public constructor Create; end; constructor TMyApplication2<T>.Create; begin inherited Create; _myencoder := TBaseEncoderClass(T).Create; end; begin var MyApp1 := TMyApplication2<TBaseEncoder>.Create; Writeln(MyApp1.ClassName); var MyApp2 := TMyApplication2<TEncoderV3>.Create; Writeln(MyApp2.ClassName); end. Share this post Link to post
aehimself 396 Posted February 13, 2020 @Kryvich I recently started to use generics myself so I guess I'm far away of harvesting their true potential. I like your solution, though; it's really elegant 🙂 Share this post Link to post
Fr0sT.Brutal 900 Posted February 13, 2020 1 hour ago, Kryvich said: Or using generics: Nice solution as well if you control creation of parent class. For example, there could be a middleware class that contains HTTP server that has client classes defined. You can't control creation of HTTP server but can modify its props so if HTTPServer.HTTPClientClass is accessible you can extend client objects. Share this post Link to post
Kryvich 165 Posted February 13, 2020 Of course HTTPServer should be "generalized" to let use it in such way. Share this post Link to post
Stefan Glienke 2006 Posted February 13, 2020 Using generics where class reference suffice is overkill and unnecessary bloat Share this post Link to post
Lars Fosdal 1792 Posted February 17, 2020 On 2/13/2020 at 12:57 PM, Stefan Glienke said: Using generics where class reference suffice is overkill and unnecessary bloat Guilty. Like OOP, Generics are sooo addictive! Share this post Link to post