php面向对象特性三

OOP继承 

继承是为了一个基类得到一个或多个类的机制。
继承自另一个类的类被称为该类的子类。这种关系通常用父类和子类来比喻。子类将继承父类的特性。这些特性由属性和方法组成。子类可以增加父类之外的新功能,因此子类是父类的”扩展“。
在PHP中,类继承通过extends关键字实现。继承自其他类的类成为子类或派生类,子类所继承的类成为父类或基类。(PHP只支持单继承,PHP不支持方法重载)。
class Computer{
    private $_name = "联想";
    public function __construct()
    {
        echo "<meta charset=utf8>";
    }

    private function __get($name)
    {
        return $this->$name;
        // TODO: Implement __get() method.
    }
    public function _run(){
        echo "我是父类";
    }
}
// 继承父类,但是子类保持为空
class NoteComputer extends Computer{

}
$notecomputer = new NoteComputer();
// 此时子类实例化对象也可以运行
echo $notecomputer->_name;
$notecomputer->_run();

 字段和方法和重写

有些时候,并不是特别需要父类的字段和方法,那么可以通过子类的重写来修改父类的字段和方法
class Computer{
    private $_name="联想";
    public function __construct()
    {
        echo "<meta charset=utf8>";
    }

    public function _run(){
        return "我是父类";
    }
}
class NoteComputer extends Computer{
    private $_name = "IBM";
    // 我不需要父类的字段和方法,那么可以采用重写的方法覆盖掉父类的字段和方法
    public function _run(){
        return "我是子类";
    }
}
$notecomputer = new NoteComputer();
echo $notecomputer->_run();

子类调用父类的字段和方法

为了安全,我们一般将父类的方法封装起来,这样,外部就无法调用,只能被继承它的子类所看到。这个时候,就需要通过子类操作来调用父类了 
class Computer{
    // protected关键字可以,只能被它继承的类调用
    protected $_name = "联想";
    public function __construct()
    {
        echo "<meta charset=utf8>";
    }

    protected function _run(){
        echo "我是父类";
    }
}
class NoteComputer extends Computer{
    public function getName(){
        return $this->_name;
    }
    public function getRun(){
        return $this->_run();
    }
}
$noteComputer1 = new NoteComputer();
echo $noteComputer1->getName();
echo $noteComputer1->getRun();

通过重写调用父类的方法

有的时候,我们需要通过重写的方法能够调用父类的方法内容,这个时候就必须使用语法:父类名::方法名() 或者 parent::方法() 即可调用 
不能以parent::属性 的形式调用
class Computer{
    protected  $_name = "联想";

    protected function _run(){
        echo "联想在运行";
    }
}
class NoteComputer extends Computer{
    public $_name = "IBM";
    public function __construct()
    {
        echo "<meta charset=utf8>";
    }
    public function getName(){
        echo  $this->_name;
        echo  parent::_run();
        echo Computer::_run();
    }
}
$notecomputer = new NoteComputer();
$notecomputer->getName();

final

final关键字可以防止类被继承,有些时候只想做独立的类,不想被其他类继承使用,那么就必须使用这个关键字,建议只要是单独的类,都加上这个关键字
final class Computer{
//无法继承的类
    // 无法继承的方法
    final public function run(){}
}
class NoteComputer extends Computer{
    //会报错
}
final class Computer{
    final public function run(){}
}
class NoteComputer extends Computer{
    public function __construct()
    {
        echo "<meta charset=utf8>";
    }

    public function run(){
        return "我被运行了";
    }
}
$noteComputer1 = new NoteComputer();
$noteComputer1->run();
报错提示:

 抽象类和方法(abstract) 

抽象方法很特殊,只在父类中声明,但在子类中实现。只有在声明abstract的类可以声明抽象方法。
规则:
    1.  抽象类不能被实例化,只能被继承
    2.  抽象方法必须被子类方法重写
//抽象类不能被实例化,就是创建对象
//抽象类是给子类用来继承的,实现一种规范和资源的共享
//只要有一个抽象方法,这个类就必须是抽象类,类前必须加上abstract
abstract class Computer{
   //抽象类允许定义属性成员字段
    public $_name = "联想";
   //抽象里的抽象方法,不能有方法体
   //抽象方法不能实现方法体内容
abstract public function run();
   //我在抽象类里能否创建普通方法
public function run2(){
    echo "我是父类的普通方法";
}
}
class NoteComputer extends Computer{
    public function __construct()
    {
        echo "<meta charset=utf8>";
    }
    //抽象类中的抽象方法,子类必须重写,不然会报错
    //抽象类的普通方法,不需要重写,子类会直接继承下来
public function run(){
        echo "我被实现了";
    }
}
$noteComputer = new NoteComputer();
$noteComputer->run();
$noteCmputer->_name();
            

接口(interface)

类不能实现多继承,但是接口可以
接口定义了实现某种服务的一般规范,声明了所需的函数和常量,但不指定如何实现,之所以不给出实现的细节,是因为不同的实体可能需要用不同的方式来实现方法定义。关键是要建立必须实现的一组一般规则,只要满足了这些原则才能说实现了这个接口。
规则:
        1.  类全部部为抽象方法(不需要声明abstract)
        2.  接口抽象方法必须是public
        3.  成员(字段)必须是常量
        
//创建一个接口
//接口也不能被实例化
//接口是为了规范实现它的子类,以达到统一的目的
interface Computer{
    //成员字段必须是常量
    const NAME = '联想';
    //接口里的方法都是抽象方法,不能够写方法体
    //并且接口的抽象方法不需要写abstract
    public function _run();
}
//调用接口常量  接口::常量
echo Computer::NAME;
//子类继承接口的方法叫做实现,接口可以多实现
class NoteComputer implements Computer{
    //必须将接口的的方法都实现
    public function _run(){
    echo "我实现了run方法";
}
}
$noteComputer = new NoteComputer();
$noteComputer->_run();
//使用类来调用接口的共享属性
NoteComputer::NAME;

到底使用接抽象类还是接口?

// 如果你要类继承多个类的方法规范,那么就使用接口
// 如果你要共享一个方法体内容,那么就用抽象类 
原文地址:https://www.cnblogs.com/anyux/p/8253576.html