I am trying to dig some PHP OOP features. Here is my sample codes
<?php
abstract class Animal{
public $name;
public function __construct($name)
{
$this->name = $name;
echo 'animal instruct' . "\n";
}
public function eat(){
return $this->name . ' is eating food.' . "\n";
}
public function __destruct()
{
echo "animal destruct" . "\n";
}
}
class Dog extends Animal{
public $name;
public function __construct($name)
{
parent::__construct($name);
}
public function bark(){
return $this->name . ' is barking.' . "\n";
}
public function __destruct()
{
echo "dog destruct" . "\n";
parent::__destruct();
}
}
class Cat extends Animal{
public $name;
public function __construct($name)
{
parent::__construct($name);
}
public function meow(){
return $this->name . ' is meowing.' . "\n";
}
public function __destruct()
{
parent::__destruct();
echo "cat destruct" . "\n";
}
}
$bobby = new Dog('Bobby');
echo $bobby->bark();
echo $bobby->eat();
$cat = new Cat("cat");
echo $cat->meow();
echo $cat->eat();
?>
When I run the code , the output is as follow
animal instruct
Bobby is barking.
Bobby is eating food.
animal instruct
cat is meowing.
cat is eating food.
animal destruct
cat destruct
dog destruct
animal destruct
When I remove this code from child classes
parent::__destruct();
the parent class is not automatically destruct itself.
What I want to know is Do we need to destruct parent class in every child classes for some free memory space or PHP will do it itself?
CodePudding user response:
There are a few things to unpick here:
- Once an object in PHP has no more references to it, the memory it uses will be freed. If it has the last reference to some other object, that object will also be freed, and so on. This is automatic, and largely invisible; you don't need to write any code in your class to make it happen, nor can you stop it happening, other than by keeping a reference to the object somewhere. (If there are circular references, they may not be freed immediately, but PHP will periodically check and free those as well.)
- When the object is freed, PHP will run a method called
__destruct
, if it exists. This method isn't responsible for freeing the object, it's just happening as an effect of PHP deciding to do so. It gives you a chance to do extra cleanup or checks as well as what PHP does automatically. - When you inherit from a class, that inheritance is part of the definition of the object; creating an instance of the sub-class doesn't actually create two objects. So in your example,
$bobby
is an instance ofDog
, and the memory that needs to be freed is the memory taken by that instance; there is no extra instance ofAnimal
"inside" it. - When you define any method in both a parent class and a sub-class, the definition in the sub-class hides the one in the parent class. If you add a definition of
eat()
in classDog
, it will be called instead of the definition inAnimal
. The same is true with "magic" methods like__destruct
: when$bobby
is freed, the engine will call$bobby->__destruct()
, and find the definition in classDog
instead of the one in classAnimal
. By callingparent::__destruct()
inside the definition ofDog
, you are explicitly asking to run the "hidden" definition.
So the answer to your final question:
Do we need to destruct parent class in every child classes for some free memory space or PHP will do it itself?
Is No. PHP will free the memory space of the object regardless of how you define the object; and there is no separate "parent memory" to free. It will additionally run the __destruct
method on that object if one exists; that method will be resolved using the normal rules: look on sub-class first, else parent, and so on.
CodePudding user response:
From the manual:
The destructor method will be called as soon as there are no other references to a particular object, or in any order during the shutdown sequence.
So it says, the parent destructor won't be called automatically, as same is for the parent constructor.
If your parent class needs to do deconstruct work, you have to call it expliticly.
Short answer
The destructor will only be called on instances.