8.10. Constructors and DestructorsIf you think back to the example where each dog had a DogTag object in it, this led to code like the following: $poppy = new Poodle; $poppy->Name = "Poppy"; $poppy->DogTag = new DogTag; $poppy->DogTag->Words = "If you find me, call 555-1234"; Using that method, if we had other objects inside each Poodle object, we would need to create the Poodle plus all its other associated objects by hand. Another way to do this is to use constructors . A constructor is a special method you add to classes that is called by PHP whenever you create an instance of the class. For example: class DogTag { public $Words; } class Dog { public $Name; public $DogTag; public function bark( ) { print "Woof!\n"; } public function _ _construct($DogName) { print "Creating a Dog: $DogName\n"; $this->Name = $DogName; $this->DogTag = new DogTag; $this->DogTag->Words = "My name is $DogName. If you find me, please call 555-1234"; } } class Poodle extends Dog { public function bark( ) { print "Yip!\n"; } } $poppy = new Poodle("Poppy"); print $poppy->DogTag->Words . "\n"; Note the _ _construct( ) method in the Dog class, which takes one variablethat is our constructor. Whenever we instantiate a Poodle object, PHP calls the relevant constructor. There are three other important things to note:
8.10.1. Parent ConstructorsTake a look at this code: class Poodle extends Dog { public function bark( ) { print "Yip!\n"; } public function _ _construct($DogName) { print "Creating a poodle\n"; } } If you replace the original Poodle definition with this new one and try running the script again, you will get the error message: "trying to get property of non-object" on the line where we have print $poppy->DogTag->Words. This is because DogTag is defined as being an instance of our DogTag class only in the Dog class constructor, and, as PHP will only ever call one constructor for us, the Dog class constructor is not called because PHP finds the Poodle constructor first. The fact that PHP always calls the "nearest" constructorthat is, if there is no child constructor, it will call the parent constructor and not the grandparent constructormeans that we need to call the parent constructor ourselves. We can do this by using the special method call parent::_ _construct( ). The "parent" part means "get the parent of this object, and use it," and the _ _construct( ) part means "Call the construct method." So the whole line means "Get the parent of this object and then call its constructor." The call to the parent's _ _construct( ) is just a normal method call, and the dog constructor needs a dog name as its parameter. So, to make the poodle Class work properly, we would need the following: class Poodle extends Dog { public function bark( ) { print "Yip!\n"; } public function _ _construct($DogName) { parent::_ _construct($DogName); print "Creating a poodle\n"; } } The output should be this: Creating Poppy Creating a poodle My name is Poppy. If you find me, please call 555-1234 Note that "Creating Poppy" is output before "Creating a poodle", which might seem backward, but it makes sense given that we call the Dog constructor before we do any Poodle code. It is always best to call parent::_ _construct( ) first from the constructor of a child class, in order to make sure all the parent's properties are set up correctly before you try and set up the new stuff. 8.10.2. DestructorsConstructors are very useful, as I am sure you will agree, but there is more: PHP also allows you to define class destructors a method to be called when an object is deleted. PHP calls destructors as soon as objects are no longer available, and the destructor method, _ _destruct( ), takes no parameters. For example: public function _ _destruct( ) { print "{$this->Name} is no more...\n"; } If you add that method into the Poodle class, all Poodles created will have that method called before being destroyed. Add that into the same script as the constructor we just defined for poodles, and run it againhere's what it outputs: Creating Poppy Creating a poodle My name is Poppy. If you find me, please call 555-1234 Poppy is no more... Like constructors, destructors are only called onceyou need to use parent::_ _destruct( ). The key difference is that you should call parent::_ _destruct( ) after the local code for the destruction, so that you are not destroying properties before using it. For example: public function _ _destruct( ) { print "{$this->Name} is no more...\n"; parent::_ _destruct( ); } 8.10.3. Deleting ObjectsSo far, our objects have been automatically destroyed at the end of the script they were created in, thanks to PHP's automatic garbage collection. However, you will almost certainly want to arbitrarily delete objects at some point in time, and this is accomplished using unset( ) in the same way as you would delete an ordinary property. It is important to note that calling unset( ) on an object will call its destructor before deleting the object, as you would expect. |