Free an object through calling destroy method of ancestor class [duplicate] - oop

This question already has an answer here:
Destructor without an override directive
(1 answer)
Closed 6 months ago.
I have multiple descendent classes sharing an ancestor. When I want to destroy an object I don't know what the actual type is, because the pointer holding the actual object has an ancestor type.
Thinks of it like you have multiple descendent from TButton, saving all objects in an array of type TButton, now when you want to destroy the objects, calling TButton(ButtonArray[I]).Destroy cause memory leaks, because it didn't call Destroy method of descendent types.
I want an approach to properly destroy descendent classes from the ancestor Destroy method.

This problem doesn't exist.
Since the destructor Destroy is a virtual method, the correct one will be chosen automatically at run-time, because Delphi knows the actual class of every object instance, no matter what kind of pointers you have to it in your source code. (Indeed, try ShowMessage(MyObj.ClassName).)
For example, given TFruit, TApple = class(TFruit), and TBanana = class(TFruit) and
var
a, b: TFruit;
begin
a := TApple.Create;
b := TBanana.Create;
a.Destroy; // calls TApple.Destroy, if properly overridden
b.Destroy; // calls TBanana.Destroy, if properly overridden
end;
(except that, of course, you never write x.Destroy but x.Free).
So why doesn't this work for you? Well, this is a common mistake:
TChild = class(TParent)
constructor Create;
destructor Destroy;
end;
must be
TChild = class(TParent)
constructor Create;
destructor Destroy; override; // <-- Add override!
end;
Otherwise you will not override TParent.Destroy, but simply introduce a new destructor with the same name.
Actually, the compiler tries to warn you about this:
[dcc32 Warning] W1010 Method 'Destroy' hides virtual method of base type 'TObject'
or something like that.

Related

How to change the instance variable of a class in Pharo?

I created a class named Die (singular of Dice) and set an instance variable side.
Object subclass: #Die
instanceVariableNames: 'side'
classVariableNames: ''
package: 'MyPackage'
I initialized the side variable to 6 by default:
initialize
side := 6.
However I would like the ability to change the instance variable after the object has been created, like so:
myDie := Die new.
myDie side: 10. " it doesn't to work "
It seems to me that instance variables can only be changed by class methods. Is there a way to change it like above?
Also, I have a method roll that returns a random number between 1 and the specified side. If I create two dice and want to roll two dice at the same time, or maybe three dice at the same time, should I create a different class, something like papercup feed that with the number of dices and implement the roll method on the papercup instead?
Thank you.
You are on a right track. When you execute
myDie side: 10.
You send a message side: to myDie which is an instance of a class Die. To "respond" to this message, the class die (or its superclasses) should implement a side: method. Ideally, this method is going to look like this:
side: aNumber
side := aNumber
You see, pharo takes encapsulation very seriously, so instance variables can be directly accessed only by the object itself, and not by anyone from the outside. This is why you always have to create accessors, which is a good practice followed to a various extent by many programming languages.
Regarding your second question: it's a good idea to have a Papercup class, but if you don't need extensive features, the exact task can be achieved by the following code:
papercup := OrderedCollection new.
papercup
add: die1;
add: die2;
add: die3.
papercup collect: #roll
This way you will roll all the 3 dies and return a collection for 3 numbers (collect: is the same as map() in many programming languages). I provided a shorthand version, whereas the full way to write a collect is: papercup collect: [ :die | die roll] when you specify a complete block (closure) and send the roll message to each die.

In Delphi, how do I enable a method pointer property in both a base class and its descendant classes

I want to create a TService descendant class that I use as the basis for my Windows service implementations. In my base class I am introducing a published ServiceDescription property, and I am using the AfterInstall event handler to write this description to the appropriate location in the Windows registry.
Note that since the TServer class (declared in Vcl.SvcMgr) is a TDataModule descendant, in order to permit the ServiceDescription property to be visible in the Object Inspector it is necessary to declare this base class in a designtime package, and register it with Delphi using a call to RegisterCustomModule. In addition, a descendant of this base class must be generated by an OTA (open tools api) wizard or some sort of code generator (both .pas and .dfm files). No problem, I've got that one sorted, and if you're interested you can read more about it from Marco Cantu's book (http://www.marcocantu.com/ddh/ddh15/ddh15e.htm).
Where I’m stuck is that I want to use the AfterInstall event handler in my base class to write to the Registry, and the AfterUninstall to remove it, but I want to ensure that my descendant classes will also support AfterInstall and AfterUninstall events.
I previously learned from Ray Konopka that if you want to reintroduce a property that you must use accessor methods in the descendant class. As a result, here is a code segment that represents my attempt to do this with respect to the AfterInstall event:
private
// field to store method pointer for the descendant AfterInstall event handler
FFAfterInstall: TServiceEvent;
…
protected
function GetAfterInstall: TServiceEvent;
procedure SetAfterInstall( value: TServiceEvent );
…
published
property AfterInstall: TServiceEvent read GetAfterInstall write SetAfterInstall;
My overridden constructor assigns a method to the inherited AfterInstall property:
constructor TTPMBaseService.Create(AOwner: TComponent);
begin
inherited;
// Hook-up the AfterInstall event handlers
Self.AfterInstall := CallAfterInstall;
…
end;
In my implementation of CallAfterInstall, after I run my code to write to the Windows Registry, I test to see if a method pointer has been assigned to my local method pointer field, and if so, I call it. It looks something like this:
procedure TTPMBaseService.CallAfterInstall(Service: TService);
var
Reg: TRegistry;
begin
// Code here to write to the Windows Registry is omitted
// Test if our method pointer field has been written to
if Assigned( FFAfterInstall ) then
FFAfterInstall( Service ); // call the method,
…
end;
I think that this all makes a lot of sense, and I think it should work. However, I’m stuck on the accessor methods. The Get accessor method compiles just fine, and here it is:
function TTPMBaseService.GetAfterInstall: TServiceEvent;
begin
Result := FFAfterInstall;
end;
But my SetAfterInstall method raises a compile-time exception, reporting that there are not enough parameters:
procedure TTPMBaseService.SetAfterInstall( value: TServiceEvent );
begin
if value <> FFAfterInstall then
FFAfterInstall := value;
end;
I’m not sure what to do here. I made the following change, and it compiles, but it does not appear to do the job:
procedure TTPMBaseService.SetAfterInstall( value: TServiceEvent);
begin
if #value <> #FFAfterInstall then
#FFAfterInstall := #value;
end;
I have two questions. The first is, am I taking the correct approach to reintroducing an event handler, all the while ensuring that both my base class, as well as its descendants, support this event? If my logic is correct, what am I doing wrong with the Setter accessor method?
Am I taking the correct approach to reintroducing an event handler?
Probably yes. Thanks to clumsy design of TService class you're not able to override a method that raises the event.
What am I doing wrong with the Setter accessor method?
The problem is in fact in your constructor:
constructor TTPMBaseService.Create(AOwner: TComponent);
begin
inherited;
// Hook-up the AfterInstall event handlers
Self.AfterInstall := CallAfterInstall;
…
end;
The comment in it indicates that you're setting inherited event handler, but that's not what the code below the comment does. Despite of assigning to Self.AfterInstall you're setting the value of reintroduced property. This is how you set inherited property:
constructor TTPMBaseService.Create(AOwner: TComponent);
begin
inherited;
// Hook-up the AfterInstall event handlers
inherited AfterInstall := CallAfterInstall;
…
end;
But my SetAfterInstall method raises a compile-time exception, reporting that there are not enough parameters.
You're getting syntax error on if statement in the setter method to be precise. It's simply because that's not how you compare method references in Delphi. See How to check if two events are pointing to the same procedure in Delphi. Why do you even need to perform such comparison? You can safely omit it.

Changing type of class field in inherited class

I am using newest Delphi 10.3.3
I have several main classes, which are extended from same parent class and also some, let's call it, Reflection classes, which has also same parent. I want instance of main class to have link to corresponding reflection instance, but I run to this issue (I simplified it to this example):
Main classes:
TMainClass = class
Link: TReflectionClass;
end;
TCarMainClass = class(TMainClass)
Link: TCarReflectionClass;
end;
Reflection classes:
TReflectionClass = class;
TCarReflectionClass = class(TReflectionClass);
The problem lies in Link field. I want Link field in TCarMainClass to be directly defined as TCarReflectionClass to avoid type-casting on lot of pieces of code (and also risking some errors), however if I define class like this, TCarMainClass.Link just hides TMainClass.Link - it is defined as different field with same name. That is not good because it consumes extra memory and mainly I can't access that field from parent class, which I want (as pointer to generic instance).
Of course I can solve this by making field private of common type and define property setter/getter which handles re-typing in each class. But that is lot of extra code for these classes and also overhead on each get/set because of calling getter/setter methods.
My question is - is there some easy hack I missed, to tell compiler I want field in child class to occupy same memory location as certain field in parent class?
Thanks
and mainly I can't access that field from parent class
While it's true that parent class can't access the descendant's field, there is nothing preventing you from synchronizing the 2.
procedure TCarMainClass.SetLink(const Value : TCarReflectionClass);
begin
FLink := Value;
TMainClass(Self).FLink := Value;
end;
Now, if you absolutely require no additionnal memory use and no setters, the only remaining option (that I can think of at this time) is as GolezTrol suggested, generics.
TMainClass<T : TReflectionClass> = class
Link: T;
end;
TCarMainClass = class(TMainClass<TCarReflectionClass>)
end;
But that would probably break your design though, because TCarMainClass would be incompatible with TMainClass<TReflectionClass>. (if you want to understand why, search for the terms covariance/contravariance).

Why do we need a constructor in OOP?

I am new to OOP. I am still in a learning phase.
Why do we need constructors, When we can initialize the values of the properties (variables) by writing a "Initialize function"?
Basically why do we write a constructor when we can achieve the same results even by writing a function for initializing the variables?
The constructor IS the "Initialize function"
Rather than calling two functions
object = new Class;
object.initialize();
You just call
object = new Class();
The logic inside the constructor can be identical to the logic inside the initialize function, but it's much tidier and avoids you naming your function initialize(), me naming mine initialize_variables(), and someone else naming theirs init_vars()... consistency is useful.
If your constructor is very large, you may still wish to split variable initialisation into a separate function and calling that function from your constructor, but that's a specific exception to the scenario.
So answer is simple
Why do we write Constructor?
Because in C you can write,
int i;
if write like this In above case data type and variable defines if you define like this memory allocated for i variable.So simple here we define class name and variable name(object name) we can create memory allocated for class name.
Example
myClass objectName;
But in C++ new keyword is used for dynamic memory allocation, so this dynamic memory which we can allocate to our class but here my example myClass is our class and we want to allocate to dynamic memory allocated.
So
myClass objectName = new myClass();
and simply constructor is memory allocation for class variable is called the constructor.`
the role of the constructor is to initialize the variables/values.it is the "initialization function".The only reason i find on why we use a constructor instead of a normal function to initialize the variables is to stop different people from using different function names and avoid ambiguity and it is much more easier to use a constructor which is instantiated automatically as soon as the class is run,instead of having to write a separate code for instantiation.this may seem small and like something that doesn't require much work,but only for a very small program,for larger ones the struggle is real.
It is usual to put mandatory things into the constructor and optional ones into the Initialise function.
For example, consider an amplifier that requires a power source so that would be supplied to its constructor. Logically, you may want to turn it on and set its power level but one could argue that you might not want to do that until later. In pseudo-code:
class Amplifier
{
public Amplifier(PowerSource powerSource)
{
// create amplifier...
}
public int PowerLevel;
public void Initialise()
{
// turn on...
}
}
The example, above, is rather puerile but it illustrates the concepts at play. It is always an issue of design, however, and opinions do vary.
Some classes of object, however, will have to perform obvious set-up operations during their construction phase. In these cases, the requirement to have a constructor is very easy to understand. For example, if your object might require a variable amount of memory, the constructor would be a logical place to allocate it and the destructor or finaliser would be a logical place to free it up again.
Even if you don't use constructor it will call implicitly by your language translator whenever you create object.Why?
The reason is that it is used for object initialization means the variable(instance) which we declare inside our class get initialized to their default value.
class Person {
//Class have two parts
//1.Data(instance variable)
//2.Methods(Sub-routine)
String name;
int age;
}
public class Stack{
public static void main(String[] args){
Person person1 = new Person();
System.out.println("Name: "+person1.name);
System.out.println("Age: " + person1.age);
}
}
Output- Name: null
Age: 0
"null" and "0" are default values which are impicitly set by default constructor.
When we initialize a class by creating an instance or object the constructor is called automatically. This is very helpful when we need a huge amount of code to be executed every time we create an object.
The best use of constructor can be seen when we create a " graphical user interface". While building a GUI for an application we need to separate the code for designing the GUI and the business logic of the application. In such a case we can write the code for designing GUI, in a constructor and business logic in respective methods. This make the code tidy and neat too.
Also when an object is created the global variables can be initialized to their default values using constructor. If we don't initialize the global variables, then the compiler will do it implicitly by using the default constructor.
So constructor is a very wise concept which appears to be an idiosyncrasy at first but as you code further and more and more you will realize it's importance.
Because constructors are exactly for that: to avoid using an "initialize function"
Plus you can have have as many constructors as you want: you juste feed them some parameters, depending how you want to inialize your object.
Constructor is a special member function which has same name as class name and called whenever object of that class is created. They are used to initialize data field in object.
Constructor has following properties:
It has same name as class name.
It is called whenever object of a class is created.
It does not have return type not even void.
It can have parameters.
Constructor can be overloaded.
Default constructor is automatically created when compiler does not find any constructor in a class.
Parameterized constructor can call default constructor using this() method.
A constructor can be static for static data field initialization.
It is not implicitly inherited.
For More Info
https://en.wikipedia.org/wiki/Constructor_(object-oriented_programming)

Matlab: Class destructor not called during clear?

In Matlab I have a class
classdef myClass
properties
% some properties here...
end
methods ( Access = 'public' )
function obj = myClass()
% constructor...
end
function obj = delete( obj )
% suppose to be destructor...
fprintf(1, 'delete\n');
end
end % public methods
end
What is the default behavior of Matlab when I clear a variable of type myClass?
For example:
>> m = myClass();
>> clear m
I would expect Matlab to call the destructor of m at this stage, but it seems like it doesn't!!
My questions:
How can I force a call to the destructor when clearing a variable?
Is this default behavior of Matlab's makes any sense? Isn't it more logical to call the destructor when clearing a variable?
Is it possible that Matlab's classes do not have a detructor method (that is, there is no default method to be called when the class is destroyed)? Or am I missing something?
Is it possible that only classes derived from handle have a destructor (the delete method)?
Thanks!
EDIT : following Jonas' answer, a brief summary:
Matlab has two types of classes: value classes (the default) and handle classes (derived from handle super class). Value classes tends to provide better performance, however, they do not have a destructor functionality.
handle classes do have a destructor function: delete that is called when the class is destroyed. See this question from more details on handle class destructors.
If one wishes to have a destructor-like functionality for value classes, Jona's answer proposes a method utilizing onCleanup functionality.
Thanks for the good answer and the insightful comments!
Delete is only defined as class destructor for handle classes, not value classes (so the answer to Q4 is "yes", see the previous link to the documentation). Value classes work very much like standard Matlab arrays, in that they're passed by value rather than by reference, and in that many of the internals, such as destructors, are hidden from the user. In exchange, they're usually faster (see for example this SO question).
Consequently, I suggest to use the onCleanup functionality if you want to have a delete method being called (note that delete(m) will not actually delete anything, so you may want to make that a private method).
classdef myTestClass
properties
% some properties here...
end
properties (Hidden)
cleanup
end
methods ( Access = 'public' )
function obj = myTestClass()
% constructor...
obj.cleanup = onCleanup(#()delete(obj));
end
end
methods ( Access = 'private' )
%# I suggest hiding the delete method, since it does not
%# actually delete anything
function obj = delete( obj )
fprintf(1, 'delete\n');
end
end % public methods
end