PHP – 抽象类(Abstract Classes)


PHP 保留字列表包括 “abstract” 关键字。当使用 “abstract” 关键字定义类时,它不能被实例化,即你不能声明此类的新对象。一个 抽象类(Abstract Class)可以由另一个类扩展。


abstract class myclass {
   // class body
}

如上所述,您不能声明此类的对象。因此,以下语句 -


 $obj = new myclass;

将导致如下所示的错误消息 -

PHP Fatal error:  Uncaught Error: Cannot instantiate abstract class myclass

抽象类可以包括属性、常量或方法。类成员可以是 publicprivate protected 类型。类中的一个或多个方法也可以定义为 abstract

如果类中的任何方法是抽象的,则该类本身必须是抽象类。换句话说,普通类不能定义抽象方法

这将引发错误 -


class myclass {
   abstract function myabsmethod($arg1, $arg2);
   function mymethod() #this is a normal method {
      echo "Hello";
   }
}

错误消息将显示为 -

PHP Fatal error:  Class myclass contains 1 abstract method 
and must therefore be declared abstract

您可以将抽象类用作父类,并使用子类对其进行扩展。但是,子类必须提供父类中每个抽象方法的具体实现,否则将遇到错误。

在下面的代码中,myclass 是一个抽象类,其中 myabsmethod() 作为抽象方法。它的派生类是 mynewclass,但它在其父类中没有抽象方法的实现。


<?php
   abstract class myclass {
      abstract function myabsmethod($arg1, $arg2);
      function mymethod() {
         echo "Hello";
      }
   }
   class newclass extends myclass {
      function newmethod() {
         echo "World";
      }
   }
   $m1 = new newclass;
   $m1->mymethod();
?>

在这种情况下,错误消息是 -

PHP Fatal error:  Class newclass contains 1 abstract method and must 
therefore be declared abstract or implement the remaining 
methods (myclass::myabsmethod) 

它指示 newclass 应该实现抽象方法,或者应该将其声明为抽象类。

示例

在下面的 PHP 脚本中,我们将 marks 作为抽象类,其中 percent() 是一个抽象方法。另一个 Student 类扩展了 marks 类并实现了它的 percent() 方法。


<?php
   abstract class marks {
      protected int $m1, $m2, $m3;
      abstract public function percent(): float;
   }

   class student extends marks {
      public function __construct($x, $y, $z) {
         $this->m1 = $x;
         $this->m2 = $y;
         $this->m3 = $z;
      }
      public function percent(): float {
         return ($this->m1+$this->m2+$this->m3)*100/300;
      }
   }

   $s1 = new student(50, 60, 70);
   echo "分数百分比: ". $s1->percent() . PHP_EOL;
?>

它将产生以下输出 -

分数百分比: 60

PHP 抽象类和接口的区别

PHP 抽象类的概念与接口非常相似。但是,接口和抽象类之间存在一些差异。

抽象类(Abstract class) 接口(Interface)
使用 abstract 关键字定义抽象类 使用 interface 关键字定义接口
抽象类无法实例化 接口无法实例化。
抽象类可以有普通方法和抽象方法 接口必须仅使用参数和返回类型声明方法,而不能使用任何 body 声明方法。
抽象类由子类扩展,子类必须实现所有抽象方法 接口必须由另一个类实现,该类必须提供接口中所有方法的功能。
可以具有 public、private 或 protected 属性 不能在 interface 中声明属性