Page 1 of 1

OOP in PHP Part Two: Con/Destructors and Encapsulation Part two of my PHP OOP guide Rate Topic: ***** 2 Votes

#1 Moonbat  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 36
  • View blog
  • Posts: 424
  • Joined: 30-June 08

Post icon  Posted 27 July 2008 - 02:56 PM

If you haven't read the first part of my tutorial, do so now.

Now we will get into two new ideas that come with classes. They are called constructors and destructors. Let's refer back to our Cheese class.

class Cheese { 
	var $type;
	var $flavor;
	var $color; 

	function giveDetails ($thetype, $theflavor, $thecolor) {
		$this->type = $thetype;
		$this->flavor = $theflavor;
		$this->color = $thecolor;
	}
	
	function showType() {
		return $this->type;
	}
	function showColor() {
		return $this->color;
	}
	function showFlavor() {
		return $this->flavor;
	}
}


In order to assign Cheese the properties of type, flavor, and color, we would have to call the giveDetails() function after declaring the new Cheese object. But what if we could do this all in one step? Here is the value of a constructor.

	function __construct($atype, $aflavor, $acolor) {
		$this->type = $atype;
		$this->flavor = $aflavor;
		$this->color = $acolor;
	}


You initialize a constructor by making a function named '__construct'. It doesn't have to take arguments; it could just echo a statement like "Object created successfully!". But in this case, we want it to take arguments. Let's see it in action.

<?php

class Cheese { 
	var $type;
	var $flavor;
	var $color; 
	
	function __construct($atype, $aflavor, $acolor) {
		$this->type = $atype;
		$this->flavor = $aflavor;
		$this->color = $acolor;
	}

	function giveDetails ($thetype, $theflavor, $thecolor) {
		$this->type = $thetype;
		$this->flavor = $theflavor;
		$this->color = $thecolor;
	}
	
	function showType() {
		return $this->type;
	}
	function showColor() {
		return $this->color;
	}
	function showFlavor() {
		return $this->flavor;
	}
}

class MoreCheese extends Cheese {
	var $cost;
	
	function giveCost($f) {
		$this->cost = $f;
	}
	
	function showCost() {
		return $this->cost;
	}
}

$zargento = new Cheese("Cheddar", "Good", "Yellow");
echo $zargento->showType();
echo "<br>";
echo $zargento->showFlavor();
echo "<br>";
echo $zargento->showColor();

?>


Output:
Cheddar
Good
Yellow


We entered the flavor, color, and type in one step, and it worked successfully. We can still use the giveDetails function later in the script if we want to change the properties of the Cheese object. Before we move on, I want to cover an aspect of older PHP versions. When wanting to use a constructor with PHP versions lower than PHP5, you must name the constructor the same name as you named the class. So for our Cheese class, instead of using __construct, you would use:

	function Cheese($atype, $aflavor, $acolor) {
		$this->type = $atype;
		$this->flavor = $aflavor;
		$this->color = $acolor;
	}


Now then, let's move on to destructors. These are called when you are finished with your object. It is useful in situations where you want to take certain actions just before the object is finished with. Suppose you have a script that is supposed to run for 20 seconds then display a message just before terminating. Someone takes that script and changes the run time to 50 seconds. Your script will display your 'termination' message after 20 seconds but the script will keep going. But by using a destructor, you are sure that this message will be displayed only when the object in question has truly served it's purpose. Here is what a destructor looks like.

	function __destruct() {
		echo "Cheese has been eaten";
	}


It looks just like the constructor, except the keyword destruct is used. A destructor usually won't take any arguments. Let's see it in action.

<?php

class Cheese { 
	var $type;
	var $flavor;
	var $color; 
	
	function __construct ($atype, $aflavor, $acolor) {
		$this->type = $atype;
		$this->flavor = $aflavor;
		$this->color = $acolor;
	}

	function giveDetails ($thetype, $theflavor, $thecolor) {
		$this->type = $thetype;
		$this->flavor = $theflavor;
		$this->color = $thecolor;
	}
	
	function showType() {
		return $this->type;
	}
	function showColor() {
		return $this->color;
	}
	function showFlavor() {
		return $this->flavor;
	}
	
	function __destruct() {
		echo "Cheese has been eaten";
	}
}

class MoreCheese extends Cheese {
	var $cost;
	
	function giveCost($f) {
		$this->cost = $f;
	}
	
	function showCost() {
		return $this->cost;
	}
}

$zargento = new Cheese("Cheddar", "Good", "Yellow");
echo $zargento->showType();
echo "<br>";
echo $zargento->showFlavor();
echo "<br>";
echo $zargento->showColor();
echo "<br>";

?>


Output:
Cheddar
Good
Yellow
Cheese has been eaten


It worked exactly how we wanted it to work.

So far, we have covered classes, constructors and destructors, and inheritance. Now we can move on to a concept called encapsulation.

Encapsulation is the idea of hiding information. For example, if you have class Car, and it has a function called giveBrand(). Now suppose you make a subclass of Car called Toyota. A Toyota object, when giveBrand() is used, will return 'Toyota'. But what if someone makes a Car object? Since a car is a generic term, giveBrand() won't really serve much purpose. What do you do?

Encapsulation helps solve this problem. There are three keywords involved with encapsulation. These are:

Public - The method is available to the base class and all subclasses
Protected - The method is available to only subclasses
Private - The method is available only to the base class

Let's see an example using our Cheese and MoreCheese classes:
<?php

class Cheese { 
	var $type;
	var $flavor;
	var $color; 
	
	function __construct($atype, $aflavor, $acolor) {
		$this->type = $atype;
		$this->flavor = $aflavor;
		$this->color = $acolor;
	}

	protected function giveDetails ($thetype, $theflavor, $thecolor) {
		$this->type = $thetype;
		$this->flavor = $theflavor;
		$this->color = $thecolor;
	}
	
	 function showType() {
		return $this->type;
	}
	 function showColor() {
		return $this->color;
	}
	 function showFlavor() {
		return $this->flavor;
	}
	
	function __destruct() {
		echo "Cheese has been eaten";
	}
}

class MoreCheese extends Cheese {
	var $cost;
	
	function giveCost($f) {
		$this->cost = $f;
	}
	
	function showCost() {
		return $this->cost;
	}
}

$zargento = new Cheese("Cheddar", "Good", "Yellow");
$zargento->giveDetails("Gorgonzola", "Awful", "Green and white");
echo $zargento->showType();
echo "<br>";
echo $zargento->showFlavor();
echo "<br>";
echo $zargento->showColor();
echo "<br>";

?>


Output:
Fatal error: Call to protected method Cheese::giveDetails() from context '' in \yada\yada\yada on line 48


See what happens? Since we protected the giveDetails() function, that means base class Cheese can't access it. We have to do the following:

1. Make another function in MoreCheese to access the protected function
2. Change $zargento from Cheese to MoreCheese.

Step #1 is done like so:

class MoreCheese extends Cheese {
	var $cost;
	
	function newGiveDetails ($thetype, $theflavor, $thecolor) {
		parent::giveDetails($thetype, $theflavor, $thecolor);
	}
	
	function giveCost($f) {
		$this->cost = $f;
	}
	
	function showCost() {
		return $this->cost;
	}
}


As you see, we used 'parent::' to get the function details of the giveDetails() function and put them in the newGiveDetails() function.

Step #2 is just a simple change. Let's see the final result:

<?php

class Cheese { 
	var $type;
	var $flavor;
	var $color; 
	
	function __construct($atype, $aflavor, $acolor) {
		$this->type = $atype;
		$this->flavor = $aflavor;
		$this->color = $acolor;
	}

	protected function giveDetails ($thetype, $theflavor, $thecolor) {
		$this->type = $thetype;
		$this->flavor = $theflavor;
		$this->color = $thecolor;
	}
	
	 function showType() {
		return $this->type;
	}
	 function showColor() {
		return $this->color;
	}
	 function showFlavor() {
		return $this->flavor;
	}
	
	function __destruct() {
		echo "Cheese has been eaten";
	}
}

class MoreCheese extends Cheese {
	var $cost;
	
	function newGiveDetails ($thetype, $theflavor, $thecolor) {
		parent::giveDetails($thetype, $theflavor, $thecolor);
	}
	
	function giveCost($f) {
		$this->cost = $f;
	}
	
	function showCost() {
		return $this->cost;
	}
}

$zargento = new MoreCheese("Cheddar", "Good", "Yellow");
$zargento->newGiveDetails("Gorgonzola", "Awful", "Green and white");
echo $zargento->showType();
echo "<br>";
echo $zargento->showFlavor();
echo "<br>";
echo $zargento->showColor();
echo "<br>";

?>


Output:
Gorgonzola
Awful
Green and white
Cheese has been eaten


Next we will take a look at private methods.

Now, take this code.

<?php

class Cheese { 
	var $type;
	var $flavor;
	var $color; 
	
	function __construct($atype, $aflavor, $acolor) {
		$this->type = $atype;
		$this->flavor = $aflavor;
		$this->color = $acolor;
	}

	private function giveDetails ($thetype, $theflavor, $thecolor) {
		$this->type = $thetype;
		$this->flavor = $theflavor;
		$this->color = $thecolor;
	}
	
	 function showType() {
		return $this->type;
	}
	 function showColor() {
		return $this->color;
	}
	 function showFlavor() {
		return $this->flavor;
	}
	
	function __destruct() {
		echo "Cheese has been eaten";
	}
}

class MoreCheese extends Cheese {
	var $cost;
	
	function giveCost($f) {
		$this->cost = $f;
	}
	
	function showCost() {
		return $this->cost;
	}
}

$zargento = new MoreCheese("Cheddar", "Good", "Yellow");
$zargento->GiveDetails("Gorgonzola", "Awful", "Green and white");
echo $zargento->showType();
echo "<br>";
echo $zargento->showFlavor();
echo "<br>";
echo $zargento->showColor();
echo "<br>";

?>


We get a fatal error. We need to do the following to use the private giveDetails() function:

1. Make a public function in base class Cheese to access the private function
2. Change $zargento from MoreCheese to Cheese

Step #1 is done with a simple function, but instead of using 'parent::' like we did for protected methods, we will use '$this'. Here is what we get:

	function newGiveDetails($thetype, $theflavor, $thecolor) {
		$this->giveDetails($thetype, $theflavor, $thecolor);
	}


Remember, all methods are public unless explicitly declared otherwise. Step #2 is very easy. Let's see the final code:

<?php

class Cheese { 
	var $type;
	var $flavor;
	var $color; 
	
	function __construct($atype, $aflavor, $acolor) {
		$this->type = $atype;
		$this->flavor = $aflavor;
		$this->color = $acolor;
	}

	private function giveDetails ($thetype, $theflavor, $thecolor) {
		$this->type = $thetype;
		$this->flavor = $theflavor;
		$this->color = $thecolor;
	}
	
	function newGiveDetails($thetype, $theflavor, $thecolor) {
		$this->giveDetails($thetype, $theflavor, $thecolor);
	}
	
	 function showType() {
		return $this->type;
	}
	 function showColor() {
		return $this->color;
	}
	 function showFlavor() {
		return $this->flavor;
	}
	
	function __destruct() {
		echo "Cheese has been eaten";
	}
}

class MoreCheese extends Cheese {
	var $cost;
	
	function giveCost($f) {
		$this->cost = $f;
	}
	
	function showCost() {
		return $this->cost;
	}
}

$zargento = new Cheese("Cheddar", "Good", "Yellow");
$zargento->newGiveDetails("Gorgonzola", "Awful", "Green and white");
echo $zargento->showType();
echo "<br>";
echo $zargento->showFlavor();
echo "<br>";
echo $zargento->showColor();
echo "<br>";

?>


The code works perfectly :D

As you can see, encapsulation provides a way to make sure that classes and subclasses have access only to what they need.

Thanks for reading, and I hope you learn something!
~Moonbat

Is This A Good Question/Topic? 1
  • +

Replies To: OOP in PHP Part Two: Con/Destructors and Encapsulation

#2 pretender19  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 36
  • Joined: 23-December 08

Posted 16 June 2009 - 03:37 AM

what is the difference between function__construct and function giveDetails ??
Was This Post Helpful? 0
  • +
  • -

#3 ShaneK  Icon User is offline

  • require_once("brain.php"); //Fatal error :/
  • member icon

Reputation: 239
  • View blog
  • Posts: 1,224
  • Joined: 10-May 09

Posted 20 June 2009 - 06:05 PM

View Postpretender19, on 16 Jun, 2009 - 03:37 AM, said:

what is the difference between function__construct and function giveDetails ??


__construct is called whenever you make the new class, it basically shortens it up...
Instead of:
$something = new class();
$something->doSomething($details);


You have:
$something = new class($details);


Hope you understand my point.

Yours,
Shane~
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1