PHP 中的面向对象编程
在 PHP 教程的这一部分中,我们将讨论 PHP 中的面向对象编程。
那里有三种广泛使用的编程范例:过程编程,函数编程和面向对象的编程。 PHP 5 支持过程式编程和面向对象的编程。 PHP 的早期版本对 OOP 的支持有限或不支持。
面向对象编程(OOP)是一种使用对象及其相互作用设计应用和计算机程序的编程范例。
OOP 中的基本编程概念是:
- 抽象
- 多态
- 封装
- 继承
抽象通过建模适合该问题的类来简化复杂的现实。 多态是将运算符或函数以不同方式用于不同数据输入的过程。 封装对其他对象隐藏了类的实现细节。 继承是一种使用已经定义的类形成新类的方法。
PHP 对象
对象是 PHP OOP 程序的基本构建块。 对象是数据和方法的组合。 在 OOP 程序中,我们创建对象。 这些对象通过方法进行通信。 每个对象都可以接收消息,发送消息和处理数据。
创建对象有两个步骤。 首先,我们创建一个类。 类是对象的模板。 它是一个蓝图,描述了类对象共享的状态和行为。 一个类可以用来创建许多对象。 在运行时从类创建的对象称为该特定类的实例。
simpleclass.php
<?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 simpleclass.php
Simple Object
(
)
object
由于类定义为空,因此我们没有太多信息。 变量的类型为object
。
PHP 对象属性
对象属性是捆绑在类实例中的数据。 对象属性称为实例变量或成员字段。 实例变量是在类中定义的变量,该类中的每个对象都有一个单独的副本。
memberfields.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 memberfields.php
Jane
Beky
我们看到了脚本的输出。 Person
类的每个实例都有$name
成员字段的单独副本。
PHP 方法
方法是在类主体内定义的函数。 它们用于通过对象的属性执行操作。 在 OOP 范式的封装概念中,方法至关重要。 例如,我们的AccessDatabase
类中可能有一个connect()
方法。 我们无需知道方法connect()
与数据库的连接方式如何。 我们只知道它用于连接数据库。 这对于划分编程中的职责至关重要,尤其是在大型应用中。
circle.php
<?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
成员只能由定义该成员的类访问。
访问修饰符可防止意外修改数据。 它们使程序更强大。
access1.php
<?php
class Person {
public $name = "";
private $age;
}
$p = new Person();
$p->name = "Jane";
#$p->age = 17;
echo $p->name . "\n";
在上面的 PHP 脚本中,我们有两个成员字段; 一个被宣布为公开,另一个被宣布为私有。
$p->name = "Jane";
#$p->age = 17;
我们从外部访问$name
成员。 在外部世界,我们的意思是“不在类中”。 可以,因为$name
变量被声明为public
。 无法访问$age
成员。 private
修饰符禁止这样做。 如果取消注释代码行,则将出现“致命错误:无法访问私有属性Person::$age
”错误。
access2.php
<?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
运行 PHP 脚本,我们收到此输出。 公共成员和受保护成员是继承的,私有成员则不是。
system.php
<?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
,width
,height
。 如果开发 Qt 的 C++ 语言没有方法重载,则库的创建者必须将其命名为drawRectRectF()
,drawRectRect()
和drawRectXYWH()
之类的方法。 方法重载的解决方案更为优雅。
overloading1.php
<?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 中不起作用。 运行此示例,我们得到以下错误:“致命错误:无法重新声明Sum::getSum()
”。 PHP 函数默认可以接受任意数量的变量。
为了模拟 PHP 中的方法重载,我们使用func_get_args()
函数。
overloading2.php
<?php
class Sum {
public function getSum() {
$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
这是overloading2.php
脚本的输出。
PHP 构造器
构造器是一种特殊的方法。 创建对象时会自动调用它。 构造器的目的是初始化对象的状态。 PHP 中的构造器名称为__construct()
(带有两个下划线)。
constructor.php
<?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
这是脚本的输出。
构造器经常会争论。
constructor2.php
<?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
现在,我们有一条消息,其中的歌曲标题印在控制台上。
在下一个示例中,我们初始化类的数据成员。 变量的初始化是构造器的典型工作。
friend.php
<?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 可以创建类常量。 这些常量不属于具体对象。 他们属于阶级。 按照约定,常量用大写字母表示。
constants.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";
我们有一个带有PI
常数的Math
类。
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 变量是否是某个类的实例化对象。
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()
特殊方法。 我们将在下面的示例中对此进行演示。
tostring.php
<?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 继承
继承是使用已经定义的类形成新类的方法。 新形成的类称为派生的类,我们派生的类称为基类。 继承的重要好处是代码重用和降低程序的复杂性。 派生类(后代)将覆盖或扩展基类(祖先)的功能。
derived.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 脚本的输出。
接下来是一个更复杂的示例。
inheritance.php
<?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();
我们创建了 4 岁的新猫:Cici。 然后,我们在 cici 对象上调用函数。 请注意,不是在Cat
类中创建而是从父类继承的方法的用法。
$ php inheritance.php
Being is alive
Cici is 4 years old
Being is not alive
脚本的输出。
PHP 抽象类和方法
PHP 5 引入了抽象类和方法。 抽象类无法实例化。 如果一个类至少包含一个抽象方法,则也必须将其声明为抽象方法。 抽象方法无法实现,它们仅声明方法的签名。 当我们从抽象类继承时,所有抽象方法都必须由派生类实现。 此外,必须以相同或较少受限制的可见性声明这些方法。
与接口不同,抽象类可能具有完全实现的方法,也可能具有定义的成员字段。 因此,抽象类可以提供部分实现。 程序员经常将一些通用功能放入抽象类中。 这些抽象类随后会被子类化以提供更具体的实现。 例如,Qt 图形库具有QAbstractButton
,它是按钮小部件的抽象基类,提供按钮所共有的功能。 按钮Q3Button
,QCheckBox
,QPushButton
,QRadioButton
和QToolButton
都从此基本抽象类继承。
正式地说,抽象类用于强制执行协议。 协议是所有实现对象都必须支持的一组操作。
abstract.php
<?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
类的子类。 它必须实现抽象区域方法。
$ php abstract.php
Circle, at x: 12, y: 45, radius: 22
Area of the circle: 1520.53084434
$x is 12
$y is 45
Output of the script.
PHP 接口
遥控器是观众和电视之间的接口。 它是此电子设备的接口。 外交礼仪指导外交领域的所有活动。 道路规则是驾车者,骑自行车者和行人必须遵守的规则。 编程中的接口类似于前面的示例。
接口是:
- API
- 合约
对象通过其公开的方法与外界交互。 实际的实现对程序员而言并不重要,或者也可能是秘密的。 公司可能会出售图书馆,但它不想透露实际的实现情况。 程序员可能会在 GUI 工具箱的窗口上调用maximize()
方法,但对如何实现此方法一无所知。 从这个角度来看,接口是对象与外界交互而不暴露其内部工作过多的方法。
从第二个角度来看,接口就是契约。 如果达成协议,则必须遵循。 它们用于设计应用的架构,并有助于组织代码。
接口是完全抽象的类型。 它们使用interface
关键字声明。 接口只能具有方法签名和常量。 接口中声明的所有方法签名必须是公共的。 他们不能具有完全实现的方法,也不能具有成员字段。 一个 PHP 类可以实现任何数量的接口。 一个接口还可以扩展任何数量的接口。 实现接口的类必须实现接口的所有方法签名。
接口用于模拟多重继承。 一个 PHP 类只能扩展一个类。 一个 PHP 类可以实现多个接口。 使用接口的多重继承与继承方法和变量无关。 它是关于继承想法或合同的,这些想法或合同由接口描述。
接口和抽象类之间有一个重要的区别。 抽象类为继承层次结构中相关的类提供部分实现。 另一方面,可以通过彼此不相关的类来实现接口。 例如,我们有两个按钮:经典按钮和圆形按钮。 两者都继承自抽象按钮类,该类为所有按钮提供了一些通用功能。 实现类是相关的,因为它们都是按钮。 另一个示例可能具有类Database
和SignIn
。 它们彼此无关。 我们可以应用ILoggable
接口,该接口将迫使他们创建执行日志记录的方法。
simpleinterface.php
<?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()
方法的实现。
下一个示例显示了一个类如何实现多个接口。
interface.php
<?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 脚本。
下一个示例显示接口如何从多个其他接口扩展。
extendinginterfaces.php
<?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 类所做的某些事情。
通常,多态是以不同形式出现的能力。 从技术上讲,它是重新定义派生类的方法的能力。 多态与将特定实现应用于接口或更通用的基类有关。
polymorphism.php
<?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 描述的第一部分。