PHP 抽象类
1. 什么是抽象类和抽象方法?
抽象类和抽象方法是指父类知道子类应该具备哪些功能,但具体如何实现这些功能则由子类自行决定。
抽象类是指包含至少一个抽象方法的类。而抽象方法是指只声明了函数签名,但没有具体代码实现的函数。
在 PHP 中,使用 abstract 关键字来定义抽象类或抽象方法:
abstract class ParentClass {
abstract public function someMethod1();
abstract public function someMethod2($name, $color);
abstract protected function someMethod3() : string;
}当从一个抽象类继承时,子类方法必须遵循以下规则:
- 子类必须实现父类中所有的抽象方法。
- 子类方法的访问修饰符必须与父类一致,或者更加宽松。例如,如果父类方法是
protected,子类可以定义为protected或public,但不能是private。 - 方法的参数数量和类型必须匹配。不过,子类可以包含额外的可选参数。
2. PHP 抽象类示例
让我们看一个例子:父类 Car 是一个抽象类。它有一个抽象方法 intro()。Audi、Volvo 和 Citroen 是 Car 的子类,它们都必须实现 intro() 方法。
代码示例:
<?php
// 父类
abstract class Car {
public $name;
public function __construct($name) {
$this->name = $name;
}
abstract public function intro() : string;
}
// 子类
class Audi extends Car {
public function intro() : string {
return "选择德国品质!我是 {$this->name}!";
}
}
class Volvo extends Car {
public function intro() : string {
return "安全第一!我是 {$this->name}!";
}
}
class Citroen extends Car {
public function intro() : string {
return "法国设计!我是 {$this->name}!";
}
}
// 创建子类对象
$audi = new Audi("Audi");
echo $audi->intro();
echo "<br>";
$volvo = new Volvo("Volvo");
echo $volvo->intro();
echo "<br>";
$citroen = new Citroen("Citroen");
echo $citroen->intro();
?>2.1 示例解析
在上述代码中:
Car类是一个抽象类,这意味着你不能直接创建它的实例(即不能$myCar = new Car())。- 它强制所有子类必须提供
intro()方法的逻辑。 - 每个子类根据自身的品牌特性,返回了不同的字符串。
2.2 更多示例
抽象方法也可以带有参数。在实现时,子类必须保证参数定义的一致性。
代码示例:
<?php
abstract class ParentClass {
// 带有参数的抽象方法
abstract protected function prefixName($name);
}
class ChildClass extends ParentClass {
public function prefixName($name) {
if ($name == "John Doe") {
$prefix = "Mr.";
} elseif ($name == "Jane Doe") {
$prefix = "Mrs.";
} else {
$prefix = "";
}
return "{$prefix} {$name}";
}
}
$class = new ChildClass;
echo $class->prefixName("John Doe");
echo "<br>";
echo $class->prefixName("Jane Doe");
?>2.3 另一个示例
如果子类在实现抽象方法时增加了额外的参数,只要这些参数带有默认值(即可选参数),程序依然可以正常运行。
代码示例:
<?php
abstract class ParentClass {
abstract protected function prefixName($name);
}
class ChildClass extends ParentClass {
// 子类定义了比父类更多的参数 ($separator, $greet)
// 但因为它们有默认值,所以符合继承规范
public function prefixName($name, $separator = ".", $greet = "Dear") {
if ($name == "John Doe") {
$prefix = "Mr";
} elseif ($name == "Jane Doe") {
$prefix = "Mrs";
} else {
$prefix = "";
}
return "{$greet} {$prefix}{$separator} {$name}";
}
}
$class = new ChildClass;
echo $class->prefixName("John Doe");
echo "<br>";
echo $class->prefixName("Jane Doe");
?>什么时候使用抽象类?
当你想要创建一个基类,但这个基类本身并不代表一个具体的实体(例如“动物”是一个抽象概念,而“猫”是具体的),并且你希望强制所有的子类都遵循某种特定的接口规范时,抽象类是最佳选择。