PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1

CHAPTER 3 ■ OBJECT BASICS



  • A protected method or property can only be accessed from within either the
    enclosing class or from a subclass. No external code is granted access.


So how is this useful to us? Visibility keywords allow you to expose only those aspects of a class that
are required by a client. This sets a clear interface for your object.
By preventing a client from accessing certain properties, access control can also help prevent bugs
in your code. Imagine, for example, that you want to allow ShopProduct objects to support a discount.
You could add a $discount property and a setDiscount() method.


// ShopProduct class
public $discount = 0;
// ...
function setDiscount( $num ) {
$this->discount=$num;
}


Armed with a mechanism for setting a discount, you can create a getPrice() method that takes
account of the discount that has been applied.


// ShopProduct class
function getPrice() {
return ($this->price - $this->discount);
}


At this point, you have a problem. You only want to expose the adjusted price to the world, but a
client can easily bypass the getPrice() method and access the $price property:


print "The price is {$product1->price}\n";


This will print the raw price and not the discount-adjusted price you wish to present. You can put a
stop to this straight away by making the $price property private. This will prevent direct access, forcing
clients to use the getPrice() method. Any attempt from outside the ShopProduct class to access the
$price property will fail. As far as the wider world is concerned, this property has ceased to exist.
Setting properties to private can be an overzealous strategy. A private property cannot be accessed
by a child class. Imagine that our business rules state that books alone should be ineligible for discounts.
You could override the getPrice() method so that it returns the $price property, applying no discount.


// BookProduct class
function getPrice() {
return $this->price;
}


Since the private $price property is declared in the ShopProduct class and not BookProduct, the
attempt to access it here will fail. The solution to this problem is to declare $price protected, thereby
granting access to descendent classes. Remember that a protected property or method cannot be
accessed from outside the class hierarchy in which it was declared. It can only be accessed from within
its originating class or from within children of the originating class.
As a general rule, err on the side of privacy. Make properties private or protected at first and relax
your restriction only as needed. Many (if not most) methods in your classes will be public, but once
again, if in doubt, lock it down. A method that provides local functionality for other methods in your
class has no relevance to your class’s users. Make it private or protected.

Free download pdf