I’m not using TObject in my Delphi code anymore. Sure I use the core classes like TStream derived from TObject but I don’t derive my own classes from TObject or descendant classes. I am using a different OOP paradigm instead.
It all started when I was looking for a simple-to-use and efficient BigInteger type in Delphi and the solution seems absolutely evident now when I am looking back at it:
type IBigNumber = interface /* interface methods */ end; type BigInteger = record private FNumber: IBigNumber; public /* public methods and overloaded operators */ end;
The BigInteger type is an interface reference wrapped in the advanced record; SizeOf(BigInteger) = SizeOf(Pointer).
Let us generalize the above idea. Instead of
type TMyObject = class /* .. */ end;
we use the alternative:
type IMyObject = interface /* .. */ end; TMyObject = record private FMyObject: IMyObject; public /* .. */ end;
You can see that the alternative requires more code typing. What we obtain for more work?
- IMyObject can be implemented in DLL and used with different programming languages;
- We obtain automatic memory management based on reference counting;
- Automatic memory management makes possible fluent coding;
- We can overload operators in TMyObject;
- We get rid of all TObject overhead.
You may ask what about inheritance and polymorphism (late binding)? These are moved from classes (TMyObject) to interfaces (IMyObject), and the move makes coding more elastic. We now have separate inheritance of interfaces and implementations, and interfaces are always polymorphic (late bound).
You can notice that interfaces in Delphi are implemented using classes derived from TInterfacedObject but as I posted before this is not necessary – interfaces can be implemented in a more compact and efficient way.
And this closes the ring; TObject is not needed.