程序员

PHP 多继承方法总结与思考

2018-09-03  本文已影响77人  半亩房顶

1、继承单接口方式

interface testA{ 
    function echostr(); 
}  
interface testB extends testA{ 
    function dancing($name); 
}  
class testC implements testB{ 
 
    function echostr(){ 
        echo "接口继承,要实现所有相关抽象方法!"; 
        echo "<br>"; 
    }  
 
    function dancing($name){ 
        echo $name."正在跳舞!";  
    }  
}  
$demo=new testC(); 
$demo->echostr(); 
$demo->dancing("模特");  
    
//运行结果
/**
    接口继承,要实现所有相关抽象方法
    模特正在跳舞!
**/

//还有另外一个例子
interface UserInterface{ //定义User的接口
    function getname();
}
interface TeacherInterface{ //teacher相关接口
    function getLengthOfService();
}
class User implements UserInterface { //实现UserInterface接口
    private $name = "tom";
    public function getName(){
        return $this->name;
    }
}
class Teacher implements TeacherInterface { //实现TeacherInterface接口
    private $lengthOfService = 5; // 工龄 
    public function getLengthOfService(){
        return $this->lengthOfService;
    }
}
// 继承自User类,同时实现了TeacherInterface接口.
class GraduateStudent extends User implements TeacherInterface {
    private $teacher ;
    public function __construct(){
        $this->teacher = new Teacher();     
    }   
    public function getLengthOfService(){
        return $this->teacher->getLengthOfService();
    }
}
class Act{
    //注意这里的类型提示改成了接口类型
    public static function getUserName(UserInterface $_user){
        echo "Name is " . $_user->getName() ."<br>";
    }
    //这里的类型提示改成了TeacherInterface类型.
    public static function  getLengthOfService(TeacherInterface $_teacher){
        echo "Age is " .$_teacher->getLengthOfService() ."<br>";
    }
}
$graduateStudent = new GraduateStudent();
Act::getUserName($graduateStudent);
Act::getLengthOfService($graduateStudent);
//结果正如我们所要的,实现了有多重身份的一个对象.

2、继承多接口方式

interface testA{
    function echostr();
}
 
interface testB{
    function dancing($name);
}
 
interface testC extends testA,testB{
    function singing($nickname);
}
 
class testD implements testC{
 
    function echostr(){
        echo "接口继承,要实现父接口所有相关方法!";
        echo "<br />";
    }
 
    function dancing($name){
        echo $name."正在跳舞!";
        echo "<br />";
    }
 
    function singing($nickname){
        echo $nickname."正在唱歌!";
    }
}
 
$demo=new testD(); 
$demo->echostr(); 
$demo->dancing("模特");  
$demo->singing("周杰伦"); 
 
//运行结果
/**
    接口继承,要实现父接口所有相关方法!
    模特正在跳舞!
    周杰伦正在唱歌!
**/

需要注意的是当你接口继承其它接口时候,直接继承父接口的静态常量属性和抽象方法,所以类实现接口时必须实现所有相关的抽象方法

3、使用trait

class Base {
    public function sayHello() {
        echo 'Hello ';
    }
}

trait SayWorld {
    public function sayHello() {
        parent::sayHello();
        echo 'World!';
    }
}

class MyHelloWorld extends Base {
    use SayWorld;

}

$o = new MyHelloWorld();
$o->sayHello();
//通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。

4、通过组合模拟多重继承

class User {
    private $name = "tom";
    public function getName(){
        return $this->name;
    }
}
class Teacher{
    private $lengthOfService = 5; // 工龄 
    public function getLengthOfService(){
        return $this->lengthOfService;
    }
}
// 上面的类中的set方法就不写了.
// 如果有个研究生,既是学生也算工龄. 
class GraduateStudent extends User {
    private $teacher ;
    public function __construct(){
        $this->teacher = new Teacher();     
    }   
    public function getLengthOfService(){
        return $this->teacher->getLengthOfService();
    }
}
$graduateStudent = new GraduateStudent();
echo "name is ".$graduateStudent->getName()."<br>";
echo "lengthOfService is ".$graduateStudent->getLengthOfService();

5、利用__call & 回调函数实现

其中使用的两个函数可以关注下,然后别忘了,恢复__call默认行为
is_callable
call_user_func_array

class Parent1 {
    function method1() {}
    function method2() {}
}
class Parent2 {
    function method3() {}
    function method4() {}
}
class Child {
    protected $_parents = array();
    public function Child(array $parents=array()) {
        $this->_parents = $parents;
    }
     
    public function __call($method, $args) {
        // 从“父类"中查找方法
        foreach ($this->_parents as $p) {
            if (is_callable(array($p, $method))) {
                return call_user_func_array(array($p, $method), $args);
            }
        }
        // 恢复默认的行为,会引发一个方法不存在的致命错误
        return call_user_func_array(array($this, $method), $args);
    }
}
$obj = new Child(array(new Parent1(), new Parent2()));
print_r( array($obj) );die;
$obj->method1();
$obj->method3();

补充内容 - 接口

思考问题:

所以,我们到底为什么要使用多继承?

emmm,这是个好问题,因为我没有答案,当然可能是我还没有遇到过必须使用多继承的场景。
不过就目前见识来看,接口,抽象类已经很足够使用了,所以私以为,可能多继承主要应用场景是一些遗留问题吧?欢迎看官指正了。

上一篇 下一篇

猜你喜欢

热点阅读