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;
到底使用接抽象类还是接口?
// 如果你要类继承多个类的方法规范,那么就使用接口 // 如果你要共享一个方法体内容,那么就用抽象类