About the "obvious" and useful or the creation and destruction of Delphi objects
When you read about a particular implementation of OOP mechanisms, it is very funny to see how a particular feature of a particular language or library is called "obvious." The description of OOP in C ++ is especially notable in this respect, in which the implementation is one of the most opaque and confusing.
So, I will not write anything about the evidence, but I will talk about a way to make life easier for you at critical points in the life cycle of objects using not “obvious”, but very useful features of the implementation of OOP in Delphi.
If the constructor stores its data only in the fields of the object, then the solution is elementary - it is enough to raise an exception. RTL Delphi itself will intercept it, call the destructor, free up used memory and throw an exception again.
Accordingly, if part of the data for construction is stored in global variables, then it is enough to use the usual try..except block with the repeated raising of an exception.
This leads to two requirements for destructors: not to provoke exceptions, which means not trying to do anything other than freeing up resources (for example, saving settings) and be sure to support ...
In Delphi, this does not present any difficulties, since any object is initialized to zeros even before the control is transferred to the constructor. Accordingly, in the destructor it is enough to correctly process null values, which is greatly helped by the FreeAndNil procedure, which frees the object only if the reference to it is no longer nil.
In Delphi, it does not matter. You can call the constructor of the ancestor, other constructors of the same class in the same way as ordinary methods or not call anything - so if you need to use the initialization of the ancestor, it is not recommended to forget to call it, but there is something to do before or instead of calling the constructor there are no ancestors.
Since in Delphi the object is immediately initialized with a final reference to VMT, there is no difference between calls to virtual methods from the constructor from other options.
In Delphi, constructors can be virtual. The meaning of this feature is the ability to create objects with an unknown class at the compilation stage without the need to implement a factory. For this purpose, variables with a reference to the class (and not an object!) Are used, for which you can call the virtual constructor by obtaining an instance of the corresponding class or its descendant, depending on the value of the link.
If an object implements one or another explicitly specified interface, then it can be brought to a link to this interface using assignment or operation as. In this case, Delphi will itself generate IUnknown method calls, which allows us not to request interfaces and not to delete objects explicitly.
On the one hand, every developer should know all of the above; on the other hand, I met not so few experienced programmers who invented bicycles only because they did not know the specifics of implementing their working tool. Hope this article helps a bit. Of the useful features of the OOP implementation in Delphi, support for delegating the implementation of interfaces remained unexamined, but this is a topic for a separate article.
So, I will not write anything about the evidence, but I will talk about a way to make life easier for you at critical points in the life cycle of objects using not “obvious”, but very useful features of the implementation of OOP in Delphi.
Handling the inability to complete object creation in the constructor
If the constructor stores its data only in the fields of the object, then the solution is elementary - it is enough to raise an exception. RTL Delphi itself will intercept it, call the destructor, free up used memory and throw an exception again.
Accordingly, if part of the data for construction is stored in global variables, then it is enough to use the usual try..except block with the repeated raising of an exception.
This leads to two requirements for destructors: not to provoke exceptions, which means not trying to do anything other than freeing up resources (for example, saving settings) and be sure to support ...
Deleting a Partially Initialized Object
In Delphi, this does not present any difficulties, since any object is initialized to zeros even before the control is transferred to the constructor. Accordingly, in the destructor it is enough to correctly process null values, which is greatly helped by the FreeAndNil procedure, which frees the object only if the reference to it is no longer nil.
Constructor call order
In Delphi, it does not matter. You can call the constructor of the ancestor, other constructors of the same class in the same way as ordinary methods or not call anything - so if you need to use the initialization of the ancestor, it is not recommended to forget to call it, but there is something to do before or instead of calling the constructor there are no ancestors.
Calling virtual methods in the constructor
Since in Delphi the object is immediately initialized with a final reference to VMT, there is no difference between calls to virtual methods from the constructor from other options.
Virtual constructors and class references
In Delphi, constructors can be virtual. The meaning of this feature is the ability to create objects with an unknown class at the compilation stage without the need to implement a factory. For this purpose, variables with a reference to the class (and not an object!) Are used, for which you can call the virtual constructor by obtaining an instance of the corresponding class or its descendant, depending on the value of the link.
Automatic control of the lifetime of an object
If an object implements one or another explicitly specified interface, then it can be brought to a link to this interface using assignment or operation as. In this case, Delphi will itself generate IUnknown method calls, which allows us not to request interfaces and not to delete objects explicitly.
Summary
On the one hand, every developer should know all of the above; on the other hand, I met not so few experienced programmers who invented bicycles only because they did not know the specifics of implementing their working tool. Hope this article helps a bit. Of the useful features of the OOP implementation in Delphi, support for delegating the implementation of interfaces remained unexamined, but this is a topic for a separate article.