[QUOTE=ServerStorm;5037468]@guido2004
Maybe we should start a new thread with an example/description of object composition with comments of when to choose over inheritance and then link the inheritance to this thread. Thoughts?[/QUOTE]
Not a bad idea at all. And definitely worthy of discussion, because PHP 5.4 brings with it traits
Generally speaking, inheritance refers to vertical inheritance. That is, each class derives from one and only one other, and so inheritance leads to classes that stack upon one another as layers of a cake. The idea goes that you proceed from the general to the specific, from the abstract to the concrete. The limit of this approach is behaviors that need to be shared between two objects.
Object composition comes in two forms. The first is to have behavior packages locked into classes of their own, and then have those classes passed to the constructors of any class needing to use those packages. The largest problem here is privacy. The object package has no real ability to interact with the host object that is using its methods. There are work arounds, but they have problems of their own.
Both object composition and inheritance make use of interfaces. Interfaces provide maps to object behaviors. If an object claims to implement an interface, it must fulfill the instructions of the interface. The problem with interfaces is simply this, what if the implementation code of the method is not going to change (or change much) between objects, even though they have disparate inheritance trees? A lesser but still significant problem is that PHP doesn’t give a mechanism for interfaces to require a function to return specific data types - though there is an RFC for this purpose.
PHP 5.4 adds traits in an attempt to address this problem. Traits provide a way to fulfill interface requirements while having the implementation code in one place. Traits also allow for multiple inheritance.
This is very powerful, and with such great power comes considerable responsibility, because the door this opens can rapidly go awry if you don’t proceed with a plan (if you do proceed with a plan though you can get some extremely tight code).
Here’s a simple trait… one that makes the protected members readable (but not writable)
trait ReadMe {
public function __get( $var ) {
if (isset($this->$var) {
return $this->$var;
} else {
trigger_error("Attempted access to non-existent property $var in " . __CLASS__, E_USER_NOTICE);
return null;
}
}
}
class PhotoPose {
use ReadMe;
protected $smile = 'cheese';
}
$pose = new PhotoPose();
echo $pose->smile; // 'cheese';
echo $pose->laugh; // nothing typed. Notice outputted if error reporting is set to return notices.
We can be more stringent if we wanted and throw an exception if a non-existent property is accessed, but throwing an error is more in line with PHP’s normal behavior.
Well, I’m tired and will continue with this later, but this should get us started.