PHP 多态

2025 年 4 月 23 日 | 阅读 8 分钟

多态性源自希腊语 Poly(意为许多)和 morphism(意为重要的结构)。

多态性是面向对象编程(也称为 OOPs)中描述模型的三大支柱之一。它是一种 OOP 设计,使不同的类能够执行或共享一个共同的接口。多态性的好处在于,在不同类中编写的代码对其所属的类没有影响,因为它们的用法是相同的。

在不同的类中,存在实现相同功能的几种技术,并且它们应该具有相同的名称。为了确保类确实遵循多态性规则,我们可以选择以下两种选择之一:抽象类或接口。

理解面向对象编程

  • OOPs,也称为面向对象编程,是一种组织代码块围绕信息和对象的编程技术,而不是围绕逻辑和函数
  • 在面向对象编程语言中工作时创建的对象是具有特定属性和特征的数据字段。
  • 面向对象编程主要关注工程师创建并希望控制以执行特定任务的数据对象,而不是关注控制对象的逻辑。
  • 这种编程方式对于具有非常高复杂性的程序或需要定期更新或维护的数据非常有效。
  • OOPs 的其他一些好处包括代码的可重用性、灵活性和效率。

OOP 的基本原则包括:

  1. 数据封装
  2. 数据抽象
  3. 继承
  4. 多态

PHP 多态

通常,多态性有两种类型:

  • 编译时多态性,也称为函数重载
  • 运行时多态性,也称为函数覆盖

编译时多态性

编译时多态性,也称为静态多态性,是指在程序编译期间解析的多态性类型。在这种形式下,调用哪个方法或函数的决定是在编译时根据方法签名或参数的数据类型做出的。编译时多态性的常见示例是函数重载和运算符重载。

注意:PHP 不支持编译时多态性,这意味着我们无法使用函数重载和运算符重载等多态性属性,这些属性在许多场景下都非常有用。在本文的后续部分,将使用运行时多态性或函数覆盖来实现多态性属性的教学。

运行时多态

运行时多态性意味着选择是在运行时(而不是在编译时)做出的,或者我们可以有一个超类实现多个子类型。函数重载是运行时多态性的一个例子。

函数覆盖 - 当我们在派生类中创建一个具有相同签名(即,总的来说,函数具有与父类中的函数相同的名称、相同的参数数量和相同的参数类型)的函数时,就称为函数覆盖。

示例:运行时多态性的使用

示例

输出

Dog barks.
Cat meows.
Cow moos.

我们在上述程序中声明了一个基类或父类 Animal()。该类包含一个方法 makeSound(),该方法已声明但未定义任何特定行为。这通过允许子类覆盖此方法为运行时多态性奠定了基础。

使用继承的概念,三个子类——Dog、Cat 和 Cow——从父类 Animal 继承。每个子类都覆盖了 makeSound() 方法,以提供自己的实现。

  • Dog 类打印“Dog barks.”。
  • Cat 类打印“Cat meows.”。
  • Cow 类打印“Cow moos.”。

为了演示多态性,我们创建了一个名为 $animals 的数组,该数组将存储不同子类的对象。尽管所有对象都存储在同一个数组中,但它们是不同类型的(Dog、Cat 和 Cow),但由于它们都继承自 Animal,因此我们可以统一对待它们。

为了运行这个数组,我们使用一个 foreach 循环,该循环遍历数组中的每个元素(对象)。在每次迭代中,都会在当前对象上调用 makeSound() 方法。在运行时,PHP 根据数组中存储的实际对象类型决定执行哪个版本的 makeSound()。这就是运行时多态性的本质——执行的方法是在程序执行期间确定的,而不是在编译期间。

PHP 多态性实现类型

PHP 可以通过两种不同的方式使用多态性。PHP 中的多态性使用 PHP 中预先提供的接口和抽象类来实现在线多态性方法。

抽象类和接口是像 PHP 这样的单继承编程语言的特殊特性,在这些语言中,多重继承是不可能的。它们有助于开发人员减少 PHP 单继承属性的限制,并有助于在具有不同层级关系的类之间自由地重用代码。它们几乎类似于类,但与类不同的是,它们始终将功能分组。

无法单独实例化一个接口,因此必须将其与类一起使用。我们可以说它们是一种类,通过同时使用多个函数来帮助开发人员实现多重继承和多态性。

接口 - 接口几乎类似于类。除此以外,它不能包含代码。接口可以声明参数和方法名称,但只能声明它们。它不能添加这些方法的实现。任何将实现接口的类都必须实现接口中定义的所有方法。

语法

使用接口实现多态性的示例

示例

输出

The area of circle is: 28.274333882308
The area of rectangle is: 12

说明

在上述程序中,我们声明了一个接口或父类Area()。我们使用了interface属性将属性从父类继承到两个子类 Circle 和 Rectangle。每个类都提供了一个函数calcArea()来展示如何使用接口方法实现运行时多态性。正如您所看到的,父类只包含函数的声明,而不包含其实现。

使用抽象类实现多态性

抽象类和方法是指父类有一个命名的方法,但希望其子类完成任务。它是一个至少包含一个抽象方法且该方法仅被声明但未在代码中实现的类。

抽象关键字通常定义一个抽象类。

在继承抽象类时,子类必须使用相同的名称和相同程度的访问修饰符/参数进行定义。因此,如果抽象类被定义为受保护,则子类必须被定义为受保护或公共。众所周知,它根本无法继承私有函数。同样,声明的变量的类型和数量应相同。但是,子类可能具有更多声明的变量或函数。

但是,在继承抽象类时,必须遵循这些规则:

  • 子类或继承类应使用相同的名称进行定义,并重新声明从父类派生的抽象方法。
  • 子类应使用相同或更低的访问修饰符进行定义。
  • 声明的变量数量应相同。但是,子类可能具有更多声明的变量或函数。

语法

使用抽象类实现多态性的示例

示例

输出

Hello!
¡Hola!
Bonjour!

说明

在上述程序中,我们声明了一个抽象类Language,该抽象类包含一个名为greet()的抽象方法或抽象函数。我们使用extends属性将属性从父类继承到三个类English, Spanish, and French,每个子类将返回不同的输出。

之后,我们声明了一个函数greeting(),该函数将接受数组作为输入,并自动调用 greet 函数。为了检索输出,我们声明了一个包含所有子类(English、Spanish 和 French)对象的数组(要调用一个类或从一个类检索输出,我们必须创建一个该特定类的对象),并将该对象作为参数传递给我们的 greeting 函数。


下一主题PHP 抽象类