PHP – 继承


继承是面向对象编程方法的基本原则之一。继承是一种软件建模方法,它支持扩展现有类的功能以构建新类,而不是从头开始构建。

PHP 提供在其对象模型中实现继承的所有功能。在 PHP 软件开发中加入继承可实现代码重用、消除冗余代码重复和逻辑组织。

假设你需要设计一个新类,其大部分功能已在现有类中明确定义。继承允许您扩展现有类、添加或删除其功能以及开发新类。事实上,PHP 有 “extends” 关键字来建立现有类和新类之间的继承关系。


class newclass extends oldclass {
   ...
   ...
}

当一个新类(以下称为继承类、子类、子类等)与现有类(将称为基类、超类、父类等)具有“IS A”关系时,继承就出现了。

PHP 继承

在 PHP 中,当通过扩展另一个类来定义一个新类时,子类会从父类继承 public protected 方法、属性和常量。您可以自由地覆盖继承方法的功能,否则它将保留父类中定义的功能。

例子

请看下面的例子 -


<?php
   class myclass {
      public function hello() {
         echo "你好,来自父类信息" . PHP_EOL;      
      }
      public  function thanks() {
         echo "谢谢,来自父类信息" . PHP_EOL;
      }
   }
   class newclass extends myclass {
      public function thanks() {
         echo "谢谢,来自子类信息" . PHP_EOL;
      }
   }

   # 父类对象
   $obj1 = new myclass;
   $obj1->hello();
   $obj1->thanks();

   # 子类对象
   $obj2 = new newclass;
   $obj2->hello();
   $obj2->thanks();
?>

它将产生以下输出 -

你好,来自父类信息
谢谢,来自父类信息
你好,来自父类信息
谢谢,来自子类信息

如前所述,子类继承父类的 public protected 成员(属性和方法),子类可以引入其他属性或方法。

在下面示例中,我们使用 Book 类作为父类。在这里,我们创建了一个扩展 Book 类的 ebook 类。

新类有一个额外的属性 – 格式 (指示电子书的文件格式 – EPUB、PDF、MOBI 等)。ebook 类定义了两个新方法来初始化和输出 ebbok 数据 – 分别是 getebook() 和 dispebook()

例子

下面给出了完整的继承代码示例——


<?php
   class Book {
   
      /* 成员变量 */
      protected int $price;
      protected string $title;

      public function getbook(string $param1, int $param2) {
         $this->title = $param1;
         $this->price = $param2;
      }
      public function dispbook() {
         echo "Title: $this->title Price: $this->price \n";
      }
   }

   class ebook extends Book {
      private string $format;
      public function getebook(string $param1, int $param2, string $param3) {
         $this->title = $param1;
         $this->price = $param2;
         $this->format = $param3;
      }
      public function dispebook() {
         echo "Title: $this->title Price: $this->price\n";
         echo "Format: $this->format \n";
      }
   }
   $eb = new ebook;
   $eb->getebook("PHP 基本知识", 450, "EPUB");
   $eb->dispebook();
?>

浏览器输出如下所示 -

Title: PHP 基本知识 Price: 450
Format: EPUB

如果你仔细看一下 getebook() 函数,前两个赋值语句实际上是 getbook() 函数,ebook 类继承了这个函数。因此,我们可以使用 parent 关键字和范围解析运算符来调用它。

使用以下命令更改 getebook() 函数代码 -


public function getebook(string $param1, int $param2, string $param3) {
   parent::getbook($param1, $param2);
   $this->format = $param3;
}

类似地,dispebook() 函数中的第一个 echo 语句被替换为对父类中 dispbook() 函数的调用 -


public function dispebook() {
   parent::dispbook();
   echo "Format: $this->format<br/>";
}

继承的构造函数

父类构造函数中的构造函数由子类继承,但如果子类定义了构造函数,则不能在子类中直接调用它。

为了运行父构造函数,需要在子构造函数中调用 parent::__construct()

例子

请看下面的例子 -


<?php
   class myclass{
      public function __construct(){
         echo "这是父构造函数". PHP_EOL;
      }
   }
   class newclass extends myclass {
      public function __construct(){
         parent::__construct();
         echo "这是子类析构函数" . PHP_EOL;
      }
   }
   $obj = new newclass();
?>

它将产生以下输出 -

这是父构造函数
这是子类析构函数

但是,如果子类没有构造函数,那么它可以像普通的类方法一样从父类继承(如果它没有声明为 private)。

例子

请看下面的例子 -


<?php
   class myclass{
      public function __construct(){
         echo "这是父构造函数". PHP_EOL;
      }
   }
   class newclass extends myclass{ }
   $obj = new newclass();
?>

将产生以下输出 -

这是父构造函数

PHP 不允许通过扩展多个父级来开发类。您可以进行 分层继承,其中类 B 扩展类 A,类 C 扩展类 B,依此类推。

但是 PHP 不支持 多重继承,其中类 C 试图同时扩展类 A 和类 B。

但是,我们可以扩展一个类并实现一个或多个接口。我们将在后续章节中学习接口