PHP 面向对象编程
上次修改时间:2025 年 5 月 18 日
在本文中,我们讨论了 PHP 中的面向对象编程。
有三种广泛使用的编程范式:过程式、函数式和面向对象。 PHP 支持过程式和面向对象编程。
面向对象编程 (OOP) 是一种使用对象及其交互来设计应用程序和计算机程序的编程范例。
OOP 中的基本编程概念是
- 抽象
- 多态
- 封装
- 继承
抽象 是通过对适用于问题的类进行建模来简化复杂的现实。 多态性 是以不同方式对不同数据输入使用运算符或函数的过程。 封装 隐藏了类的实现细节,不让其他对象知道。 继承 是一种使用已经定义的类来形成新类的方法。
PHP 对象
对象是 PHP OOP 程序的基本构建块。 对象是数据和方法的组合。 在一个 OOP 程序中,我们创建对象。 这些对象通过方法相互通信。 每个对象都可以接收消息、发送消息和处理数据。
创建对象有两个步骤。 首先,我们创建一个类。 一个 类 是一个对象的模板。 它是一个蓝图,描述了该类的对象都共享的状态和行为。 一个类可以用来创建许多对象。 在运行时从一个类创建的对象被称为该特定类的 实例。
<?php class Simple {} $object = new Simple(); print_r($object); echo gettype($object), "\n";
在我们的第一个例子中,我们创建一个简单的对象。
class Simple {}
这是一个简单的类定义。模板的主体是空的。它没有任何数据或方法。
$object = new Simple();
我们创建一个 Simple
类的新实例。 为此,我们有 new
关键字。 $object
变量是创建的对象的句柄。
print_r($object); echo gettype($object), "\n";
我们使用 print_r
函数来获取关于对象的信息,使用 gettype
函数来获取变量的类型。
$ php simple_class.php Simple Object ( ) object
我们没有获得太多信息,因为类定义是空的。 变量的类型是 object
。
PHP 对象属性
对象属性是捆绑在一个类实例中的数据。 对象属性被称为 实例变量 或 成员字段。 实例变量是在类中定义的变量,类的每个对象都有一个单独的副本。
<?php class Person { public $name = ""; } $p1 = new Person(); $p1->name = "Jane"; $p2 = new Person(); $p2->name = "Beky"; echo $p1->name . "\n"; echo $p2->name . "\n";
在上面的 PHP 脚本中,我们有一个 Person
类,其中有一个成员字段。
$p1 = new Person(); $p1->name = "Jane";
我们创建了 Person 类的一个实例,并将 $name
变量设置为“Jane”。 我们使用 -> 运算符来访问对象的属性。
$p2 = new Person(); $p2->name = "Beky";
我们创建了 Person 类的另一个实例。 这里我们将变量设置为“Beky”。
echo $p1->name . "\n"; echo $p2->name . "\n";
我们将变量的内容打印到控制台。
$ php member_fields.php Jane Beky
我们看到脚本的输出。 Person
类的每个实例都有 $name
成员字段的单独副本。
PHP 方法
方法是在类的正文中定义的函数。 它们用于对我们对象的属性执行操作。 方法在 OOP 范式的 封装 概念中至关重要。 例如,我们可能在 AccessDatabase 类中有一个 connect
方法。 我们不需要被告知方法 connect
是如何准确地连接到数据库的。 我们只知道它用于连接到数据库。 这对于划分编程中的责任至关重要,尤其是在大型应用程序中。
<?php class Circle { public $radius; function setRadius($radius) { $this->radius = $radius; } function area() { return $this->radius * $this->radius * M_PI; } } $c = new Circle(); $c->setRadius(5); echo $c->area(), "\n";
在代码示例中,我们有一个 Circle
类。 我们定义了两种方法。
public $radius;
我们有一个成员字段。 它是圆的半径。 public
关键字是一个访问说明符。 它告诉该变量可以从外部世界完全访问。
function setRadius($radius) { $this->radius = $radius; }
这是 setRadius
方法。 它是一个普通的 PHP 函数。 我们将类中定义的函数称为 方法。 $this
变量是一个特殊变量,我们使用它从方法访问成员字段。
function area() { return $this->radius * $this->radius * M_PI; }
area
方法返回圆的面积。 M_PI
是一个内置常量。
$ php circle.php 78.539816339745
PHP 访问修饰符
访问修饰符 设置方法和成员字段的可见性。 PHP 有三个访问修饰符:public
、protected
和 private
。 public
成员可以从任何地方访问。 protected
成员只能在类本身以及继承的类和父类中访问。 private
成员只能由定义成员的类访问。
访问修饰符保护数据免受意外修改。 它们使程序更加健壮。
<?php class Person { public $name = ""; private $age; } $p = new Person(); $p->name = "Jane"; #$p->age = 17; echo $p->name . "\n";
在上面的 PHP 脚本中,我们有两个成员字段;一个声明为 public,另一个声明为 private。
$p->name = "Jane"; #$p->age = 17;
我们从外部世界访问 $name
成员。 通过外部世界,我们指的是“不在类中”。 这是可以的,因为 $name
变量被声明为 public
。 访问 $age
成员是不可能的。 private
修饰符禁止这样做。 如果我们取消注释代码行,我们会得到“Fatal error: Cannot access private property Person::$age”错误。
<?php class Base { public $name = "Base"; protected $id = 6124; private $is_defined = "yes"; } class Derived extends Base { public function info() { echo "This is Derived class\n"; echo "Members inherited: \n"; echo $this->name . "\n"; echo $this->id . "\n"; echo $this->is_defined . "\n"; } } $derived = new Derived(); $derived->info();
在此 PHP 脚本中,我们有一个 Derived
类,它扩展了 Base
类。 Base
类有三个成员字段,所有成员字段都有不同的访问修饰符。 $is_defined
成员未被继承。 private
修饰符阻止了这一点。
public function info() {
info
方法有一个 public
访问修饰符。 这意味着它可以在类环境之外调用。
$ php access2.php This is Derived class Members inherited: Base 6124
public 和 protected 成员被继承,private 成员不被继承。
<?php class SysInfo { private function get_date() { return date("Y/m/d"); } private function get_version() { return phpversion(); } public function getInfo() { $date = $this->get_date(); $version = $this->get_version(); echo "The date is: $date\n"; echo "The PHP version is: $version\n"; } } $sys = new SysInfo(); $sys->getInfo(); #$sys->get_date();
在这个脚本中,我们有一个 SysInfo
类。 它将一些系统信息输出到控制台。 我们有两个私有函数和一个公共函数。 私有方法仅用于 SysInfo
类的内部工作。 它们不应该在类外调用。
$sys = new SysInfo(); $sys->getInfo(); #$sys->get_date();
我们创建一个 SysInfo
类的实例,并调用公开可用的 getInfo
方法。 getInfo
方法在内部使用私有方法来完成它的工作。 取消注释最后一行代码会导致错误。
PHP 方法重载
方法重载允许创建多个具有相同名称的方法,但这些方法在输入类型上彼此不同。
方法重载有什么用? Qt4 库给出了一个很好的使用示例。 QPainter
类有三种方法来绘制矩形。 它们的名称是 drawRect
,它们的参数不同。 一个接受对浮点矩形对象的引用,另一个接受对整数矩形对象的引用,最后一个接受四个参数:x、y、宽度、高度。 如果 C++ 语言(Qt 的开发语言)没有方法重载,那么库的创建者将不得不将方法命名为 drawRectRectF
、drawRectRect
、drawRectXYWH
。 使用方法重载的解决方案更优雅。
<?php class Sum { public function getSum() { return 0; } public function getSum($x) { return $x; } public function getSum($x, $y) { return $x + $y; } } $s = new Sum(); echo $s->getSum() . "\n" ; echo $s->getSum(5) . "\n" ; echo $s->getSum(3, 4) . "\n" ;
这是一种方法重载,我们从 C#、Java 或 C++ 等语言中得知。 但这在 PHP 中不起作用。 运行此示例,我们得到以下错误:“Fatal error: Cannot redeclare Sum::getSum()”。 默认情况下,PHP 函数可以接受任意数量的变量。
为了在 PHP 中模拟方法重载,我们使用 func_get_args
函数。
<?php class Sum { public function getSum() { $sum = 0; $args = func_get_args(); if (empty($args)) return 0; foreach ($args as $arg) { $sum += $arg; } return $sum; } } $s = new Sum(); echo $s->getSum() . "\n" ; echo $s->getSum(5) . "\n" ; echo $s->getSum(3, 4) . "\n" ; echo $s->getSum(3, 4, 7) . "\n" ;
这次,脚本将运行。
$args = func_get_args();
func_get_args
函数返回一个包含函数参数列表的数组。
foreach ($args as $arg) { $sum += $arg; }
我们遍历数组的所有成员,并计算总和。
echo $s->getSum() . "\n" ; echo $s->getSum(5) . "\n" ; echo $s->getSum(3, 4) . "\n" ; echo $s->getSum(3, 4, 7) . "\n" ;
我们使用不同数量的输入调用相同的方法名称。
$ php overloading2.php 0 5 7 14
PHP 构造函数
构造函数是一种特殊的方法。 当对象被创建时,它会自动被调用。 构造函数的目的是启动对象的状态。 PHP 中构造函数的名称是 __construct
(带两个下划线)。
<?php class Song { function __construct() { echo "Song object is created \n"; } } $song = new Song();
我们有一个 Song
类。 这个类有一个构造函数,它将消息打印到控制台。
$song = new Song();
这是创建对象并调用构造函数的时候。 我们在控制台中收到一条消息。
$ php constructor.php Song object is created
构造函数通常接受参数。
<?php class Song { function __construct($song) { echo "Song $song is created \n"; } } $song = new Song("Bad romance");
我们稍微修改了之前的示例。 我们将一个值传递给构造函数。
function __construct($song) { echo "Song $song is created \n"; }
传递的参数存储在本地 $song
变量中。
$ php constructor2.php Song Bad romance is created
现在我们有一条消息,其中包含打印到控制台的歌曲标题。
在下一个例子中,我们初始化该类的数据成员。初始化变量是构造函数的典型工作。
<?php class Friend { private $born; private $name; function __construct($name, $born) { $this->name = $name; $this->born = $born; } function getInfo() { echo "My friend $this->name was born in $this->born\n"; } } $friend = new Friend("Monika", 1990); $friend->getInfo();
我们有一个 Friend
类,其中包含数据成员和方法。
private $born; private $name;
我们在类定义中有两个变量。 private
关键字是一个访问修饰符。 它是一种封装形式。 private
关键字是限制最严格的修饰符。 它只允许相关对象访问该变量。 没有后代,也没有其他对象。 稍后将详细介绍此主题。
function __construct($name, $born) { $this->name = $name; $this->born = $born; }
在构造函数中,我们初始化了两个数据成员。 $this
变量是一个用于引用对象变量的句柄。
$friend = new Friend("Monika", 1990); $friend->getInfo();
我们使用两个参数创建了一个 Friend 对象。 然后我们调用该对象的 getInfo
方法。 要调用对象方法,我们使用 ->
运算符。
$ php friend.php My friend Monika was born in 1990
PHP 构造函数属性提升
构造函数属性提升是 PHP 8.0 中引入的一个特性,它允许您直接在构造函数参数列表中声明和初始化类属性。 这减少了样板代码,并使类定义更简洁。
<?php class User { public function __construct( public string $name, private int $age, protected string $email ) {} } $user = new User("Alice", 30, "alice@example.com"); echo $user->name . "\n"; // echo $user->age; // Error: private property // echo $user->email; // Error: protected property
在此示例中,User
类使用构造函数属性提升。 name
属性是 public 的,age
是 private 的,email
是 protected 的。 这些属性会自动从构造函数参数中声明和初始化。
此功能对于数据传输对象和具有许多属性的类特别有用,使您的代码更短且更易于阅读。
PHP 类常量
PHP 能够创建类常量。 这些常量不属于具体对象。 它们属于类。 按照惯例,常量用大写字母书写。
<?php class Math { const PI = 3.14159265359; public function getPI() { echo self::PI; } } $math = new Math(); echo Math::PI, "\n"; echo $math->getPI(), "\n";
我们有一个 Math 类,其中包含一个 PI 常量。
const PI = 3.14159265359;
const
关键字用于定义常量。
public function getPI() { echo self::PI; }
从方法内部访问类常量,使用 self
关键字,后跟两个冒号。
echo Math::PI, "\n"; echo $math->getPI(), "\n";
我们将 PI
常量打印到控制台。 在第一种情况下,我们通过引用类名(后跟两个冒号和常量名)来获取常量值。 请注意,不需要任何对象即可获取类常量。 在第二种情况下,我们使用对象方法。
PHP instanceof 关键字
instanceof
关键字用于确定 PHP 变量是否是某个类的实例化对象。
<?php class Cat {} class Dog {} class Bird {} $objects = [ new Cat(), new Dog(), new Cat(), new Bird(), new Bird(), new Dog(), new Dog(), new Cat(), new Bird() ]; shuffle($objects); foreach ($objects as $object) { if ($object instanceof Cat) { echo "It is a Cat\n"; } elseif ($object instanceof Dog) { echo "It is a Dog\n"; } else if ($object instanceof Bird) { echo "It is a Bird\n"; } }
在上面的脚本中,我们有三个类:Cat
、Dog
和 Bird
。 我们遍历数组,并为每个数组值打印类。
$objects = [ new Cat(), new Dog(), new Cat(), new Bird(), new Bird(), new Dog(), new Dog(), new Cat(), new Bird() ];
我们创建了一个这些对象的数组。
shuffle($objects);
我们打乱了数组。 此时,我们不知道数组值的类类型。
if ($object instanceof Cat) { echo "It is a Cat\n"; }
这里我们使用 instanceof
关键字来找出类的类型。
$ php instanceof.php It is a Bird It is a Cat It is a Cat It is a Dog It is a Dog It is a Cat It is a Dog It is a Bird It is a Bird
PHP __toString 方法
当我们对对象实例使用 print
或 echo
关键字时,将调用 __toString
特殊方法。 我们将在以下示例中演示这一点。
<?php class Cat { public $name; public $age; function __construct($name, $age) { $this->age = $age; $this->name = $name; } function __toString() { return "Cat: $this->name, Age: $this->age \n"; } } $missy = new Cat("Missy", 6); $lucky = new Cat("Lucky", 4); print $missy; echo $lucky;
我们有一个 Cat 类,其中定义了一个 __toString
特殊方法。
function __toString() { return "Cat: $this->name, Age: $this->age \n"; }
该方法打印有关对象的基本信息。
$missy = new Cat("Missy", 6); $lucky = new Cat("Lucky", 4);
我们创建了 Cat 类的两个对象。
print $missy; echo $lucky;
我们对它们使用 print
或 echo
关键字。
$ php tostring.php Cat: Missy, Age: 6 Cat: Lucky, Age: 4
PHP 继承
继承是一种使用已经定义的类来形成新类的方法。 新形成的类被称为 派生 类,我们从中派生的类被称为 基 类。 继承的重要好处是代码重用和程序复杂性的降低。 派生类(后代)覆盖或扩展基类(祖先)的功能。
<?php class Base { function __construct() { echo "Construction of Base class \n"; } } class Derived extends Base { function __construct() { parent::__construct(); echo "Construction of Derived class \n"; } } $obj1 = new Base(); $obj2 = new Derived();
在此 PHP 脚本中,我们有两个类:一个 Base
类和一个 Derived
类。 Derived
类继承自 Base
类。
class Derived extends Base {
在 PHP 中,我们使用 extends
关键字来创建继承关系。
function __construct() { parent::__construct(); echo "Construction of Derived class \n"; }
在 Derived 类的构造函数中,我们调用父构造函数。 我们使用 parent
关键字,后跟两个冒号和 __construct
方法。 必须显式调用父类的构造函数。
$obj1 = new Base(); $obj2 = new Derived();
我们实例化了 Base
类和 Derived
类。
$ php derived.php Construction of Base class Construction of Base class Construction of Derived class
接下来是一个更复杂的示例。
<?php abstract class Being { protected $isAlive = true; public function isAlive() { if ($this->isAlive) { echo "Being is alive\n"; } else { echo "Being is not alive\n"; } } public function kill() { $this->isAlive = false; } } abstract class Animal extends Being { protected $age; public function __construct($age) { $this->age = $age; } protected function setAge($age) { $this->age = $age; } public function getAge() { return $this->age; } } class Cat extends Animal { private $name; public function __construct($name, $age) { $this->name = $name; parent::__construct($age); } public function getName() { return $this->name; } } $cat = new Cat("Cici", 4); $cat->isAlive(); echo $cat->getName() . " is " . $cat->getAge() . " years old\n"; $cat->kill(); $cat->isAlive();
我们在这里使用了几个新概念。 在代码示例中,我们有三个类:Being
、Animal
和 Cat
。 Animal
类继承自 Being
类。 Cat
类继承自 Animal
类。 类继承未声明为私有的方法和数据成员。
abstract class Being {
Being
类被声明为 abstract
。 abstract
关键字禁止实例化类。 创建 Being
类的实例没有多大意义。
protected $isAlive = true;
$isAlive
数据成员被声明为 protected
。 只有定义它们的类及其后代才能访问此类成员。
abstract class Animal extends Being {
Animal
类也被声明为抽象。 它继承自类 Being
。 为此,我们使用 extends
关键字。 Animal
是一个后代。 它继承了基类 Being
的方法和变量。
class Cat extends Animal {
Cat
类继承自 Animal
类。 它继承自 Animal
类,也间接继承自 Being
类。 它未声明为抽象,这意味着我们可以实例化它。
parent::__construct($age);
在 Cat
类的构造函数中,我们使用 parent
关键字(后跟两个冒号和 __construct
方法)调用父构造函数。 必须显式调用父类的构造函数。
$cat = new Cat("Cici", 4); $cat->isAlive(); echo $cat->getName() . " is " . $cat->getAge() . " years old\n"; $cat->kill(); $cat->isAlive();
我们创建了一只新猫:Cici,4 岁。 然后我们在 cici 对象上调用函数。 请注意使用未在 Cat
类中创建,而是从父类继承的方法。
$ php inheritance.php Being is alive Cici is 4 years old Being is not alive
PHP 抽象类和方法
抽象类不能被实例化。 如果一个类包含至少一个抽象方法,它也必须被声明为抽象。 抽象方法不能被实现,它们只是声明了方法的签名。 当我们从一个抽象类继承时,派生类必须实现所有抽象方法。 此外,这些方法必须使用相同或更宽松的可见性来声明。
与接口不同,抽象类可以拥有带有完整实现的方法,也可以定义成员字段。因此,抽象类可以提供部分实现。程序员经常将一些公共功能放入抽象类中。然后将这些抽象类进行子类化以提供更具体的实现。例如,Qt 图形库有一个 QAbstractButton
,它是按钮小部件的抽象基类,提供按钮的公共功能。按钮 Q3Button
、QCheckBox
、QPushButton
、QRadioButton
和 QToolButton
继承自这个抽象基类。
正式来说,抽象类用于强制执行协议。协议是一组所有实现对象必须支持的操作。
<?php abstract class Drawing { protected $x = 0; protected $y = 0; public abstract function area(); public function getCoordinates() { echo "\$x is $this->x\n"; echo "\$y is $this->y\n"; } } class Circle extends Drawing { private $radius; public function __construct($x, $y, $r) { $this->radius = $r; $this->x = $x; $this->y = $y; } public function area() { return $this->radius * $this->radius * pi(); } public function __toString() { return "Circle, at x: $this->x, y: $this->y, radius: $this->radius"; } } $o = new Circle(12, 45, 22); echo "$o \n"; echo "Area of the circle: " . $o->area() . "\n"; echo $o->getCoordinates();
在我们的 PHP 脚本中,我们有一个抽象基类 Drawing
。该类定义了两个成员字段,定义了一个方法并声明了一个方法。其中一个方法是抽象的,另一个方法是完全实现的。 Drawing
类是抽象的,因为我们无法绘制它。我们可以绘制一个圆,一个点或一个正方形。 Drawing
类具有我们可以绘制的对象的某些公共功能。
class Circle extends Drawing {
Circle
是 Drawing
类的子类。它必须实现抽象的 area 方法。
$ php abstract.php Circle, at x: 12, y: 45, radius: 22 Area of the circle: 1520.53084434 $x is 12 $y is 45
PHP 接口
遥控器是观众和电视之间的接口。它是此电子设备的接口。外交协议指导外交领域的所有活动。道路规则是驾驶者、骑自行车者和行人必须遵守的规则。编程中的接口与之前的例子类似。
接口是
- API
- 约定
对象通过它们暴露的方法与外界交互。实际的实现对程序员来说并不重要,或者它也可能是一个秘密。一家公司可能出售一个库,并且它不想公开实际的实现。程序员可能会在 GUI 工具包的窗口上调用一个 maximize
方法,但对该方法的实现方式一无所知。从这个角度来看,接口是对象与外界交互的方法,而无需过多地暴露其内部工作原理。
从第二个角度来看,接口是合同。如果达成一致,就必须遵守。它们用于设计应用程序的架构,并帮助组织代码。
接口是完全抽象的类型。它们使用 interface
关键字声明。接口只能有方法签名和常量。在接口中声明的所有方法签名都必须是公共的。它们不能有完全实现的方法,也不能有成员字段。一个 PHP 类可以实现任意数量的接口。一个接口也可以扩展任意数量的接口。实现接口的类必须实现接口的所有方法签名。
接口用于模拟多重继承。一个 PHP 类只能扩展一个类。一个 PHP 类可以实现多个接口。使用接口的多重继承不是关于继承方法和变量。它是关于继承思想或合同,这些思想或合同由接口描述。
接口和抽象类之间有一个重要的区别。抽象类为在继承层次结构中相关的类提供部分实现。另一方面,接口可以由彼此不相关的类实现。例如,我们有两个按钮:一个经典按钮和一个圆形按钮。两者都继承自一个抽象按钮类,该类为所有按钮提供一些公共功能。实现类是相关的,因为所有都是按钮。另一个例子可能有类 Database
和 SignIn
。它们彼此无关。我们可以应用一个 ILoggable
接口,这将迫使它们创建一个用于进行日志记录的方法。
<?php interface IInfo { public function do_inform(); } class Some implements IInfo { public function do_inform() { echo "This is a Some class\n"; } } $sm = new Some(); $sm->do_inform();
这是一个简单的 PHP 脚本,演示了一个接口。
interface IInfo { public function do_inform(); }
这是一个接口 IInfo
。它具有 do_inform
方法签名。
class Some implements IInfo {
我们使用 implements
从接口实现。
public function do_inform() { echo "This is a Some class\n"; }
该类为 do_inform
方法提供了实现。
下一个示例展示了类如何实现多个接口。
<?php interface Device { public function switch_on(); public function switch_off(); } interface Volume { public function volume_up(); public function volume_down(); } interface Pluggable { public function plug_in(); public function plug_off(); } class CellPhone implements Device, Volume, Pluggable { public function switch_on() { echo "Switching on\n"; } public function switch_off() { echo "Switching off\n"; } public function volume_up() { echo "Volume up\n"; } public function volume_down() { echo "Volume down\n"; } public function plug_in() { echo "Plugging in\n"; } public function plug_off() { echo "Plugging off\n"; } } $o = new CellPhone(); $o->switch_on(); $o->volume_up(); $o->plug_in();
我们有一个 CellPhone 类,它继承自三个接口。
class CellPhone implements Device, Volume, Pluggable {
该类实现了所有三个接口,这些接口用逗号分隔。CellPhone
类必须实现所有三个接口的所有方法签名。
$ php interface.php Switching on Volume up Plugging in
下一个示例展示了接口如何从多个其他接口扩展。
<?php interface IInfo { public function do_inform(); } interface IVersion { public function get_version(); } interface ILog extends IInfo, IVersion { public function do_log(); } class DBConnect implements ILog { public function do_inform() { echo "This is a DBConnect class\n"; } public function get_version() { echo "Version 1.02\n"; } public function do_log() { echo "Logging\n"; } public function connect() { echo "Connecting to the database\n"; } } $db = new DBConnect(); $db->do_inform(); $db->get_version(); $db->do_log(); $db->connect();
在这个 PHP 脚本中,我们定义了三个接口。扩展接口允许我们组织它们。
interface ILog extends IInfo, IVersion { public function do_log(); }
ILog
接口扩展了另外两个接口。
public function do_inform() { echo "This is a DBConnect class\n"; }
DBConnect
类实现了 do_inform
方法。此方法由 ILog
接口继承,该类实现了该接口。
PHP 多态
多态性是使用运算符或函数以不同方式处理不同数据输入的过程。在实际中,多态性意味着如果类 B 继承自类 A,它不必继承关于类 A 的所有内容;它可以以不同的方式做一些类 A 做的事情。
一般来说,多态性是呈现不同形式的能力。从技术上讲,它是一种为派生类重新定义方法的能力。多态性涉及将特定实现应用于接口或更通用的基类。
<?php abstract class Shape { private $x = 0; private $y = 0; public abstract function area(); } class Rectangle extends Shape { function __construct($x, $y) { $this->x = $x; $this->y = $y; } function area() { return $this->x * $this->y; } } class Square extends Shape { function __construct($x) { $this->x = $x; } function area() { return $this->x * $this->x; } } $shapes = [ new Square(5), new Rectangle(12, 4), new Square(8) ]; foreach ($shapes as $shape) { echo $shape->area() . "\n"; }
在上面的 PHP 脚本中,我们有一个抽象的 Shape
类。这个类变形为两个后代类:Rectangle
和 Square
。两者都提供了它们自己对 area
方法的实现。多态性为 OOP 系统带来了灵活性和可扩展性。
在本文中,我们介绍了 PHP 中的 OOP。
作者
来源
列出所有 PHP 教程。