Here is some clarification about PHP inheritance – there is a lot of bad information on the net. PHP does support Multi-level inheritance. (I tested it using version 5.2.9). It does not support multiple inheritance.
This means that you cannot have one class extend 2 other classes (see the extends keyword). However, you can have one class extend another, which extends another, and so on.
Example:
<?php
class A {
// more code here
}
class B extends A {
// more code here
}
class C extends B {
// more code here
}
$someObj = new A(); // no problems
$someOtherObj = new B(); // no problems
$lastObj = new C(); // still no problems
?>
Object Inheritance
Inheritance is a well-established programming principle, and PHP makes use of this principle in its object model. This principle will affect the way many classes and objects relate to one another.
For example, when you extend a class, the subclass inherits all of the public and protected methods from the parent class. Unless a class overrides those methods, they will retain their original functionality.
This is useful for defining and abstracting functionality, and permits the implementation of additional functionality in similar objects without the need to reimplement all of the shared functionality.
Przykład #1 Inheritance Example
<?php
class foo
{
public function printItem($string)
{
echo 'Foo: ' . $string . PHP_EOL;
}
public function printPHP()
{
echo 'PHP is great.' . PHP_EOL;
}
}
class bar extends foo
{
public function printItem($string)
{
echo 'Bar: ' . $string . PHP_EOL;
}
}
$foo = new foo();
$bar = new bar();
$foo->printItem('baz'); // Output: 'Foo: baz'
$foo->printPHP(); // Output: 'PHP is great'
$bar->printItem('baz'); // Output: 'Bar: baz'
$bar->printPHP(); // Output: 'PHP is great'
?>
Object Inheritance
jackdracona at msn dot com
15-Apr-2010 03:53
15-Apr-2010 03:53
php at sleep is the enemy dot co dot uk
07-Apr-2010 09:36
07-Apr-2010 09:36
Here's fun, an attempt to make some degree of multiple inheritance work in PHP using mixins. It's not particularly pretty, doesn't support method visibility modifiers and, if put to any meaningful purpose, could well make your call stack balloon to Ruby-on-Rails-esque proportions, but it does work.
<?php
abstract class Mix {
protected $_mixMap = array();
public function __construct(){
$this->_mixMap = $this->collectMixins($this);
}
public function __call($method, $args){
// doesn't pass scope
//return call_user_func_array(array($className, $method), $args);
// Error: Given object is not an instance of the class this method was declared in
//$method = new ReflectionMethod($className, $method);
//return $method->invokeArgs($this, $args);
$payload = $this->buildMixinPayload($this->_mixMap, $method, $args);
if(!$payload) throw new Exception('Method ' . $method . ' not found');
list($mixinMethod, list($method, $args)) = $payload;
return $this->$mixinMethod($method, $args);
}
protected function collectMixins($class){
static $found = array();
static $branch = array();
if(empty($branch)) $branch[] = get_class($this);
$mixins = array();
foreach(array_reverse(get_class_methods($class)) as $method){
if(preg_match('/^mixin(\w+)$/', $method, $matches)){
$className = $matches[1];
if(in_array($className, $branch))
throw new Exception('Circular reference detected ' . implode(' > ', $branch) . ' > ' . $className);
if(!in_array($className, $found)){
if(!class_exists($className)) throw new Exception('Class ' . $className . ' not found');
// populate props from mixin class
foreach(get_class_vars($className) as $key => $value){
if(!property_exists($this, $key)) $this->$key = $value;
}
$found[] = $branch[] = $className;
$mixins[$className] = $this->collectMixins($className);
}
$branch = array(get_class($this));
}
}
return $mixins;
}
protected function buildMixinPayload($mixins, $method, $args){
foreach($mixins as $className => $parents){
$mixinMethod = 'mixin' . $className;
if(method_exists($className, $method)) return array($mixinMethod, array($method, $args));
if(!empty($parents) && $return = $this->buildMixinPayload($parents, $method, $args)){
return array($mixinMethod, $return);
}
}
return false;
}
}
?>
php at sleep is the enemy dot co dot uk
31-Mar-2010 03:47
31-Mar-2010 03:47
Here's some example usage of the mixin class.
<?php
class Lunch extends Mix {
public $edible = true;
/*
* Circular references are, of course, illegal and will be detected
*/
/*
public function mixinSteakAndKidneyPie($method, $args){
return SteakAndKidneyPie::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
}
//*/
public function isEdible($affirm, $negate){
return $this->edible ? $affirm : $negate;
}
}
class Pie extends Mix {
/*
* class tokens are bound at compile time so need to be explicitly declared
* Need to make sure there are enough argument placeholders to cover all mixed in methods of Lunch
* Late static binding may improve this situation
*/
public function mixinLunch($method, $args){
return Lunch::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
}
public function buildPie($sep = ','){
return 'Crust' . $sep . $this->getFilling() . $sep . 'More Crust';
}
public function getFilling(){
$this->edible = false;
return 'Baking beans';
}
}
class SteakAndKidney extends Mix {
public function mixinLunch($method, $args){
return Lunch::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
}
/*
* everything to be mixed in must be public
* protected/private methods called from within mixed in methods will fail
*/
public $filling = 'Steak and Kidney';
public function getFilling(){
$this->edible = true;
return $this->filling;
}
}
class SteakAndKidneyPie extends Mix {
/*
* order of mixin declaration significant
* later declarations override earlier ones
*/
public function mixinSteakAndKidney($method, $args){
return SteakAndKidney::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
}
public function mixinPie($method, $args){
return Pie::$method(@$args[0], @$args[1], @$args[2], @$args[3], @$args[4], @$args[5]);
}
/*
* Pick specific methods like so:
*/
//*
public function getFilling(){
return SteakAndKidney::getFilling();
}
//*/
}
$pie = new SteakAndKidneyPie();
echo $pie->buildPie(' | ');
echo '<br/>Pie ' . $pie->isEdible('is', 'is not') . ' Edible';
/*
OUTPUTS:
Crust | Steak and Kidney | More Crust
Pie is Edible
*/
?>
jarrod at squarecrow dot com
27-Oct-2009 02:01
27-Oct-2009 02:01
You can force a class to be strictly an inheritable class by using the "abstract" keyword. When you define a class with abstract, any attempt to instantiate a separate instance of it will result in a fatal error. This is useful for situations like a base class where it would be inherited by multiple child classes yet you want to restrict the ability to instantiate it by itself.
Example........
<?php
abstract class Cheese
{
//can ONLY be inherited by another class
}
class Cheddar extends Cheese
{
}
$dinner = new Cheese; //fatal error
$lunch = new Cheddar; //works!
?>
