Visibility (public, private, protected)
The visibility of class members, (properties, methods), relates to how that member may be manipulated within, or from outside the class. Three levels of visibilty exist for class members.- public
- private
- protected
Public class members (properties and methods) are available through-out the script and may be accessed from outside the class as we demonstrated in our car class. Lets create a simple new class to demonstrate.
class mathematics{/*** a number ***/public $num;
/**
*
* Add two to a number
*
* @access public
*
* @return int
*
**/public function addTwo(){
return $this->num+2;
}
}/*** end of class ***/
/*** Instantiate a new class instance ***/$math = new mathematics;
/*** set the value of the number ***/$math->num = 2;
/*** call the addTwo method ***/echo $math->addTwo();
?>
class mathematics{
/*** a number ***/private $num;
/**
*
* Set the value of $num
*
* @access public
*
* @param $num The number to set
*
* @return int
*
**/public function setNum($num){
$this->num = $num;
}
/**
*
* Add two to a number
*
* @access public
*
* @return int
*
**/public function addTwo(){
return $this->num+2;
}
}/*** end of class ***/
/*** Instantiate a new class instance ***/$math = new mathematics;
/*** set the value of the number ***/$math->setNum(2);
/*** call the addTwo method ***/echo $math->addTwo();
?>
?>
Fatal error: Cannot access private property mathematics::$num in /www/mathematics.class.php on line 43
Even if you were to try to access the private $num property from a child class it would fail. This is because private methods and properties in a parent class are not visible to child classes and cannot be accessed. To access a parent method or property from a child class you need to use the protected keyword. Like the private keyword, protetected methods and properties are available only to the class that created them. But unlike private, protected methods and properties are visible from a parent class. Lets see how this works.
class mathematics{/*** a number ***/protected $num;
/**
*
* Set the value of $num
*
* @access public
*
* @param $num The number to set
*
* @return int
*
**/public function setNum($num){
$this->num = $num;
}
/**
*
* Add two to a number
*
* @access public
*
* @return int
*
**/public function addTwo(){
return $this->num+2;
}
}/*** end of class ***/
class divide extends mathematics{
/**
*
* Divide a number by two
*
* @access public
*
* @return int
*
**/public function divideByTwo(){
/*** divide number by two ***/
$new_num = $this->num/2;
/*** return the new number and round to 2 decimal places ***/
return round($new_num, 2);
}
} /*** end of class ***/
/*** Instantiate a new class instance ***/$math = new divide;
/*** set the value of the number ***/$math->setNum(14);
echo $math->divideByTwo();
?>
Final
As we saw in the previous section there are ways to protect your code from being used in an improper manner. Another way of protecting yourself is the Final keyword. Any method or class that is declared as Final cannot be overridden or inherited by another class. Lets put it to the test.
final class mathematics{
} /*** end of class ***/
class divide extends mathematics{
}
?>
Fatal error: Class divide may not inherit from final class (mathematics) in /www/final.php on line 8
This can protect us from those who wish to use our code for a purpose other than that for which it was intended.
Abstract Classes
An abstract class is a class that cannot be instantiated on its own. You cannot create a new object from it. To see this lets make a basic class.
abstract class mathematics{
/**
*
* Add two to a number
*
* @access public
*
* @return int
*
**/public function addTwo(){
return $this->num+2;
}
} /*** end of class ***/
/*** try to create new object from the mathematics class ***/$math = new mathematics
?>
Fatal error: Cannot instantiate abstract class mathematics in /www/abstract.php on line 23.
As you can see, this is not allowed. Also if you declare any class method to be abstract, you must also declare the class itself as abstract too. So, whats the point you ask? Well, you can inherit from an abstract class. Any class that extends an abstract parent class must create an interface of the parent abstract methods. If this is not done a fatal error is generated. This ensures that the implementation is correct.
abstract class mathematics{/*** child class must define these methods ***/abstract protected function getMessage();
abstract protected function addTwo($num1);
/**
*
* method common to both classes
*
**/public function showMessage() {
echo $this->getMessage();
}
} /*** end of class ***/
class myMath extends mathematics{/**
*
* Prefix to the answer
*
* @return string
*
**/protected function getMessage(){
return "The anwser is: ";
}
/**
*
* add two to a number
*
* @access public
*
* @param $num1 A number to be added to
*
* @return int
*
**/public function addTwo($num1) {
return $num1+2;
}
} /*** end of class ***/
/*** a new instance of myMath ***/$myMath = new myMath;/*** show the message ***/$myMath->showMessage();/*** do the math ***/echo $myMath->addTwo(4);
?>
Static Methods and Properties
The use of the static keyword allows class members (methods and properties) to be used without needing to instantiate a new instance of the class. The static declaratin must come after the visibility declaration, eg:public static myClass{
Because there is no object created when using a static call, the keyword $this and the arrow operator, -> are not available. Static variables belong to the class itself and not to any object of that class. To access withing the class itself you need to use the self keyword along with the :: scope resolution operator. Lets whip up a quick example of using static.
/*** a simple class ***/class myClass{/*** a static variable ***/ static $foo;
}
/** give the static variable a value ***/myClass::$foo = 'Bar';
/*** echo the static variable ***/echo (myClass::$foo ).?>
Bar This is rather basic as an example, so lets use something practical. Static properties are often used as counters. Here we will use a basic counter class.
class counter{
/*** our count variable ***/private static $count = 0;
/**
* Constructor, duh
**/function __construct() {
self::$count++;
}
/**
*
* get the current count
*
* @access public
*
* @return int
*
**/public static function getCount() {
return self::$count;
}
} /*** end of class ***/
/*** create a new instance ***/$count = new counter(); /*** get the count ***/echo counter::getCount() . '
';/*** create another instance ***/$next = new counter(); /*** echo the new count ***/echo counter::getCount().'
'; /*** and a third instance ***/$third = new counter;
echo counter::getCount().'
';?>
Interfaces
Interfaces in PHP allow you to define a common structure for your classes. An interface cannot be instantiated on its own. One of the goals of OOP is re-use of code. Interfaces make this a much easier process. The interface methods have no internal logic, they are simply a "mapping" or constraint of what the class, or classes, should implement. Here we will demonstrate how this works using our vehicle class from earlier, with the addition of a stop() function. class vehicle implements testdrive{
/*** define public properties ***/
/*** the color of the vehicle ***/public $color;
/*** the number of doors ***/public $num_doors;
/*** the price of the vehicle ***/public $price;
/*** the shape of the vehicle ***/public $shape;
/*** the brand of vehicle ***/public $brand;
/*** the constructor ***/public function __construct(){
echo 'About this Vehicle.
';
}
/*** define some public methods ***/
/*** a method to show the vehicle price ***/public function showPrice(){
echo 'This vehicle costs '.$this->price.'.
';
}
/*** a method to show the number of doors ***/public function numDoors(){
echo 'This vehicle has '.$this->num_doors.' doors.
';
}
/*** method to drive the vehicle ***/public function drive(){
echo 'VRRROOOOOOM!!!';
}/**
* a method to stop the car
*
* @access public
*
**/public function stop(){
echo 'SSSCCRRREEEEEECCHH!!!
';
}
} /*** end of class ***/
/*** declare our interface ***/interface testdrive{/*** some functions that must be implemented ***/function drive();
function stop();
}
/*** an new vehicle object ***/$object = new vehicle;
/*** call some methods ***/$object->drive();$object->stop();?>
In the real world interfaces provide us with the tools harness parts of multiple classes. Consider this scenario. If we had two classes, one for a fax and the other for a printer. Each has seperate uses and could be described like this:
class fax{
public function dial();
public function send();
public function recieve();
}
class printer{
public function printBlack();
public function printColor();
public function printDraft();
}?>
class fax{
public function dial();
public function send();
public function recieve();
}
class printer extends fax{
public function printBlack();
public function printColor();
public function printDraft();
public function kick();
}
class printerFax extends fax{
}
$object = new printerFax;?>
To counter this problem an interface can be used to tell the classes what functions (methods) are required. Lets look at the design.
interface fax{
public function dial();
public function send();
public function recieve();
}
interface printer{
public function printBlack();
public function printColor();
public function printDraft();
public function kick();
}
class printerFax implements fax, printer{
public function dial(){ }
public function send(){ }
public function recieve(){ }
public function printBlack(){ }
public function printColor(){ }
public function printDraft(){ }
public function kick(){ }
}
$object = new printerFax;?>
public function kick(){ }
and run it again. What you should now get is an error such as:
Fatal error: Class printerFax contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (printer::kick) in /www/oop.php on line 22
With the kick() function removed from our implementation, we have essentially broken the contract that says we will implement every function (method) specified in the interface. We can gather these functions fractionally from multiple classes, but we MUST have them all or we will get errors such as the one above.
Interfaces play a major role in with SPL and it is recommend you implement the interfaces from SPL and not just the class methods.
No comments:
Post a Comment