PHP继承怎么用?类继承和方法重写详解?

文章导读
Previous Quiz Next 继承是面向对象编程方法论的基本原则之一。继承是一种软件建模方法,它允许扩展现有 class 的功能来构建新 class,而不是从零开始构建。
📋 目录
  1. PHP 中的 Class 继承
  2. PHP 中的继承类型
  3. Is-a 关系
  4. 多级继承示例
  5. 继承中的访问修饰符
  6. PHP 中方法覆盖的示例
  7. 继承和扩展功能的示例
  8. 继承中的构造函数
  9. Final 关键字的使用
  10. 继承的限制
A A

PHP - 继承



Previous
Quiz
Next

继承是面向对象编程方法论的基本原则之一。继承是一种软件建模方法,它允许扩展现有 class 的功能来构建新 class,而不是从零开始构建。

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

PHP 中的 Class 继承

假设你需要设计一个新 class,其大部分功能已经在现有 class 中定义得很好。继承允许你扩展现有 class,添加或移除其特性并开发新 class。事实上,PHP 使用 "extends" 关键字来建立现有 class 和新 class 之间的继承关系。

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

PHP 中的继承类型

PHP 中有三种继承类型 −

  • 单继承:一个子 class 从一个父 class 继承。

  • 多级继承:一个 class 从其子 class 继承。

  • 层次继承:多个 class 从同一个父 class 派生,从而形成层次继承。

Is-a 关系

当一个新 class(以下简称继承 class、子 class、子类等)与一个现有 class(以下简称基 class、超 class、父 class 等)具有 "IS A" 关系时,继承就派上用场了。

PHP Inheritance

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

多级继承示例

下面的代码展示了一个多级继承的示例 −

<?php
   class Animal {  
      public function sound() {  
         echo "Animals make sound\n";  
      }  
   }  
   
   class Dog extends Animal {  
      public function bark() {  
         echo "Dog barks\n";  
      }  
   }  
   
   class Puppy extends Dog {  
      public function weep() {  
         echo "Puppy weeps\n";  
      }  
   }  
   
   $myPuppy = new Puppy();  
   $myPuppy->sound(); 
   $myPuppy->bark();  
   $myPuppy->weep();  
?> 

这将产生下面的 输出

Animals make sound
Dog barks
Puppy weeps

继承中的访问修饰符

下面的代码展示了如何使用访问修饰符,这些修饰符决定属性和方法是否可以在 class 外部或内部使用 −

<?php
   class Animal {  
      public $name = "Lion";  
      protected $type = "Wild";  
      private $age = 5;  
   
      public function getAge() {  
         return $this->age;  
      }  
   }  
   
   class Cat extends Animal {  
      public function showType() {  
         return $this->type;  
      }  
   }  
   
   $myCat = new Cat();  
   echo $myCat->name."\n";     
   echo $myCat->showType()."\n";
   echo $myCat->getAge()."\n";
?> 

这将产生下面的 输出

Lion
Wild
5

PHP 中方法覆盖的示例

请查看以下示例 −

<?php
   class myclass {
      public function hello() {
         echo "Hello from the parent class" . PHP_EOL;      
      }
      public  function thanks() {
         echo "Thank you from parent class" . PHP_EOL;
      }
   }
   class newclass extends myclass {
      public function thanks() {
         echo "Thank you from the child class" . PHP_EOL;
      }
   }

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

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

它将产生以下 output

Hello from the parent class
Thank you from parent class
Hello from the parent class
Thank you from the child class

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

在以下示例中,我们使用 Book class 作为父类。这里,我们创建一个 ebook class,它扩展了 Book class。新类有一个额外的属性 - format(表示 ebook 的文件格式 - EPUB、PDF、MOBI 等)。ebook class 定义了两个新方法来初始化和输出 ebook 数据 - 分别是 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 Fundamentals", 450, "EPUB");
   $eb->dispebook();
?>

浏览器 output 如以下所示 −

Title: PHP Fundamentals Price: 450
Format: EPUB

如果你仔细查看 getebook() 函数,前两个赋值语句实际上就是 getbook() 函数的内容,该函数已被 ebook class 继承。因此,我们可以使用 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();
?>

它将产生以下 输出

This is parent constructor
This is child class destructor

然而,如果子类没有构造函数,则它可以像普通类方法一样从父类继承(如果未声明为 private)。

示例

查看以下示例 −

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

它将产生以下 输出

This is parent constructor

Final 关键字的使用

在以下示例中,我们使用了 final 关键字。如果不希望方法或类被继承或修改,则使用 final 关键字。

<?php
   class Animal {  
      final public function sound() {  
         echo "Animals make sound";  
      }  
   }  
   
   class Dog extends Animal {  
      // 这将产生错误
      // public function sound() {  
      //     echo "Dog barks";  
      // }  
   }  
   
   $myDog = new Dog();  
   $myDog->sound();
?> 

输出

以上代码的输出如下 −

Animals make sound 

继承的限制

PHP 不允许通过扩展多个父类来开发一个类。你可以拥有 hierarchical inheritance,其中 class B 扩展 class A,class C 扩展 class B,依此类推。但 PHP 不支持 multiple inheritance,即 class C 试图同时扩展 class A 和 class B。不过,我们可以扩展一个类并实现一个或多个 interfaces。我们将在后续章节中学习接口。