PHP继承

71 阅读2分钟

继承

使用关键字extends来继承一个类

class Child extends Parent {
}
class A{
    var $name = '张三';
    function demo(){
		echo $this->name;
    }
}

class B extends A{
    var $name = '李四';
}

$b = new B();
$b->demo(); // 李四

继承之后可以对父类属性方法进行重写

class B extends A{
	function demo(){
        echo $this->name . '棒棒棒!';
    }
}
$b = new B();
$b->demo(); // 张三棒棒棒!

如果继承时,不想二次覆盖重写父类的构造函数,可以类似使用Python的super方法:parent::__construct

// 一个父类
class A{
    public $name;
    function __construct($name){
        $this->name = $name;
    }
}
// 子类继承父类并利用父类方法
class B extends A{
    public $age;
    function __construct($name, $age)
    {
        parent::__construct($name);  // 子类构造方法调用父类方法
        $this->age = $age;
    }
}

接口

接口通过interface关键字来定义的,接口中定义的所有方法都必须是公有,这是接口的特性

接口中无法定义构造函数,但是可以定义常量


实现类可以使用implements继承接口类,实现类中必须实现所有的接口类方法

interface iTemplate
{
    public function setVariable($name, $var);
    public function getHtml($template);
}
class Template implements iTemplate
{
    private $vars = array();
    public function setVariable($name, $var){
        $this->vars[$name] = $var;
    }
  
    public function getHtml($template){
        foreach($this->vars as $name => $value) {
            $template = str_replace('{' . $name . '}', $value, $template);
        }
        return $template;
    }
}

接口像是一种协议,所有继承接口类都将遵循接口的方法实现

抽象

使用abstract定义抽象类,定义为抽象的类不能被实例化

继承一个抽象类的时候,子类必须定义父类中的所有抽象方法,这些方法的访问控制必须和父类中一样,或者更为宽松

抽象类中的抽象方法不可以定义为私有,不然无法让子类继承,外部访问不到

abstract class AbstractClass
{
 // 强制要求子类定义这些方法
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);

    // 普通方法(非抽象方法)
    public function printOut() {
        print $this->getValue() . PHP_EOL;
    }
}

子类必须定义所有父类的抽象方法,但可以不定义其他普通方法

class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
    
    public function abc(){
        echo "hahah";
    }
}

此外,子类方法可以包含父类抽象方法中不存在的可选参数

一般继承抽象类和接口,要将extends语句写在implements前面

抽象类可以继承抽象类,且不能重写抽象父类的抽象方法

abstract class  Human
{
    abstract function eat();
}

abstract class Sutdent extends Human
{
    abstract function study();
    abstract function eat(); 
}

若重写抽象父类的抽象方法eat()会报错Fatal error: Can't inherit abstract function Human::eat() (previously declared abstract in Sutdent)


  • 抽象类和接口类联系
  1. 都是用于声明某一种事物,规范名称、参数,形成模块
  2. 无详细的实现细节
  3. 都可以用继承,接口可以继承接口形成新的接口,抽象类可以继承抽象类从而形成新的抽象类
  • 抽象类和接口类区别
  1. 抽象类可以有属性、普通方法、抽象方法,但接口不能有属性、普通方法、可以有常量
  2. 抽象类可以有构造函数,接口没有
  3. 一个类只继承一个抽象类,但可以继承多个接口

总结:抽象类声明是什么,接口类声明做什么