PHP 简明教程

PHP 继承

1. 什么是继承?

在面向对象编程中,继承是指一个类派生自另一个类。

子类(Child Class)将继承父类(Parent Class)中所有公共(public)和受保护(protected)的属性和方法。此外,子类还可以拥有自己独特的属性和方法。

继承是通过 extends 关键字来实现的。

2. 继承示例

在下面的示例中,Strawberry(草莓)类继承自 Fruit 类。这意味着 Strawberry 类可以使用 Fruit 类的公共属性 $name$color,以及公共方法 intro()

代码示例:

<?php
class Fruit {
  public $name;
  public $color;
  public function __construct($name, $color) {
    $this->name = $name;
    $this->color = $color;
  }
  public function intro() {
    echo "这颗水果是 {$this->name},颜色是 {$this->color}。";
  }
}

// Strawberry 继承自 Fruit
class Strawberry extends Fruit {
  public function message() {
    echo "我是一颗草莓还是一个类?";
  }
}

$strawberry = new Strawberry("草莓", "红色");
$strawberry->message();
$strawberry->intro();
?>

3. 继承与 Protected 访问修饰符

在之前的“访问修饰符”章节中,我们提到 protected 属性或方法可以在类内部以及派生类中访问。那这意味着什么呢?

让我们看一个尝试在类外部调用受保护方法的例子:

代码示例(错误示范):

<?php
class Fruit {
  public $name;
  public $color;
  public function __construct($name, $color) {
    $this->name = $name;
    $this->color = $color;
  }
  protected function intro() {
    echo "这颗水果是 {$this->name},颜色是 {$this->color}。";
  }
}

class Strawberry extends Fruit {
  public function message() {
    echo "我是一颗草莓还是一个类?";
  }
}

$strawberry = new Strawberry("草莓", "红色");
$strawberry->message(); // OK
$strawberry->intro(); // 错误!该方法是受保护的,无法从类外部调用
?>

如果我们通过子类内部的一个公共方法来调用这个受保护的方法,它就能正常工作:

代码示例(正确做法):

<?php
class Strawberry extends Fruit {
  public function message() {
    echo "我是一颗草莓还是一个类?";
    // 在子类内部调用受保护的方法
    $this->intro();
  }
}

$strawberry = new Strawberry("草莓", "红色");
$strawberry->message(); // OK,内部间接调用了受保护的方法
?>

4. 重写继承的方法 (Overriding)

继承而来的方法并非一成不变。子类可以通过定义一个与父类同名的方法来**重写(Override)**父类的行为。

在下例中,Strawberry 类重写了父类 Fruit__construct()intro() 方法:

代码示例:

<?php
class Fruit {
  public $name;
  public $color;
  public function __construct($name, $color) {
    $this->name = $name;
    $this->color = $color;
  }
  public function intro() {
    echo "这颗水果是 {$this->name},颜色是 {$this->color}。";
  }
}

class Strawberry extends Fruit {
  public $weight;
  public function __construct($name, $color, $weight) {
    $this->name = $name;
    $this->color = $color;
    $this->weight = $weight;
  }
  public function intro() {
    echo "这颗水果是 {$this->name},颜色是 {$this->color},重量是 {$this->weight} 克。";
  }
}

$strawberry = new Strawberry("草莓", "红色", 50);
$strawberry->intro();
?>

5. final 关键字

final 关键字可以用来防止类被继承,或者防止方法被重写。

既然你写了一个完美的类,不希望别人再通过继承来“乱改”它,那么 final 就是你的终极武器。

5.1 防止类继承

代码示例:

<?php
final class Fruit {
  // 一些代码
}

// 错误!无法从 final 类继承
class Strawberry extends Fruit {
  // 一些代码
}
?>

5.2 防止方法重写

代码示例:

<?php
class Fruit {
  final public function intro() {
    // 一些代码
  }
}

class Strawberry extends Fruit {
  // 错误!无法重写 final 方法
  public function intro() {
    // 一些代码
  }
}
?>