<?php
 /**
 * 类的扩展/抽象/最终
 * 1. protected: 受保护/可继承
 * 2. extends: 扩展/继承
 * 3. parent: 父类引用
 * 4. abstract: 抽象
 * 5. final: 最终类
 */
 // 父类, 基类, 超类
class Person
{
    // protected: 成员可继承,可以在子类中使用
    protected $name;
    // private: 私有, 仅限当前类, 子类,外部都不可见
    private $id = 12345;
    // public: 类中,子类, 类外都可见
    public function __construct($name)
    {
        $this->name = $name;
    }
     // getInfo::protected
    // 比protected再严格的是 private, 比它更宽松的是: public
    protected function getInfo()
    {
        return $this->name;
    }
}
 // 学生类
// extends: Stu这个类,扩展了Person类的功能 
class Stu extends Person
{
    // 1. 属性扩展
    private $lesson;
    private $score;
     // 2. 方法扩展/重写
    public function __construct($name, $lesson, $score)
    {
        // 引用了父类的构造方法
        // parent: 父类引用 Person
        parent::__construct($name);
        $this->lesson = $lesson;
        $this->score = $score;
    }
     public function getInfo()
    {
        // $this->name 
        // return $this->name . "同学, ($this->lesson : $this->score 分)";
        return parent::getInfo() . "同学, ($this->lesson : $this->score 分)";
    }
}
 $stu = new Stu('小狗', 'PHP', 88);
echo $stu->getInfo();
 echo '<hr>';
$person = new Person('小猪');
// var_dump只打印属性
var_dump($person);
echo '<hr>';
 // 如果不想让用户直接使用父类,而必须通过继承/扩展的子类来间接使用
// 将父类声明为一个抽象类
abstract class Demo1
{
}
 // (new Demo1);
 class Demo2 extends Demo1
{
}
//返回当前脚本中已声明类的名称
echo 'Demo2的父类是: ' . get_parent_class(new Demo2);
 echo '<hr>';
 abstract class Demo3
{
    // hello 方法已经被实现了
    // protected function hello()
    // {
    //     // ...
    // }
    //程序中,有些类的作用只是用来继承,无须实例化;
    //为了满足类的这种需求,php提供了抽象类的概念 ,关键词abstract;
    // 抽象方法: 只有方法名,参数列表,没有具体实现(大括号)
    // 抽象类不能被实例化
    // 有抽象方法的类一定是抽象类;类必须要abstract修饰
    // 抽象方法不能有函数体;即abstract function fun();
    // 抽象类中的非抽象方法,可以被子类调用
    // 非抽象子类继承抽象类,子类必须实现父类的所有抽象方法
    // 抽象子类继承抽象类,无需继承父类的抽象方法
    abstract protected function hello($name);
}
 class Demo4 extends Demo3
{
    // 工作类Demo4中必须实现父类中的抽象成员
    public function hello($name)
    {
        return 'Hello , ' . $name;
    }
}
// call_user_func 调用类下的 hello方法,并替换参数传递
echo call_user_func([new Demo4, 'hello'], '牛老师');
 echo '<hr>';
 // 如果一个类不用扩展,直接当成工作类/直接干活的,直接new
// 为了防止被继承, 可声明为最终类
// final class Demo5
// {
// }
 // class Demo6 extends Demo5
// {
// }
 //抽象类的具体说明
//作用:抽象类不实现具体方法,具体方法由子类完成。
//定义抽象类 abstract
abstract class A{
    //abstract 定义抽象类的方法,这里没有花括号。子类必须实现这个抽象方法。
    abstract public function say();
    //抽象类可以有参数
    abstract public function eat($argument);
    //在抽象类中可以定义普通的方法。
    public function run(){
      echo '这是run方法';
    }
}
class B extends A{
//子类必须实现父类的抽象方法,否则是致命的错误。
public function say(){
    echo '这是say方法,实现了抽象方法';
}
public function eat($argument){
    echo '抽象类可以有参数 ,输出参数:'.$argument;
}
}
$b =new B;
$b->say();
echo '<br>';
$b->eat('apple');
echo '<br>';
$b->run();