ZetCode

PHP 面向对象编程

上次修改时间:2025 年 5 月 18 日

在本文中,我们讨论了 PHP 中的面向对象编程。

有三种广泛使用的编程范式:过程式、函数式和面向对象。 PHP 支持过程式和面向对象编程。

面向对象编程 (OOP) 是一种使用对象及其交互来设计应用程序和计算机程序的编程范例。

OOP 中的基本编程概念是

抽象 是通过对适用于问题的类进行建模来简化复杂的现实。 多态性 是以不同方式对不同数据输入使用运算符或函数的过程。 封装 隐藏了类的实现细节,不让其他对象知道。 继承 是一种使用已经定义的类来形成新类的方法。

PHP 对象

对象是 PHP OOP 程序的基本构建块。 对象是数据和方法的组合。 在一个 OOP 程序中,我们创建对象。 这些对象通过方法相互通信。 每个对象都可以接收消息、发送消息和处理数据。

创建对象有两个步骤。 首先,我们创建一个类。 一个 是一个对象的模板。 它是一个蓝图,描述了该类的对象都共享的状态和行为。 一个类可以用来创建许多对象。 在运行时从一个类创建的对象被称为该特定类的 实例

simple_class.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 simple_class.php
Simple Object
(
)
object

我们没有获得太多信息,因为类定义是空的。 变量的类型是 object

PHP 对象属性

对象属性是捆绑在一个类实例中的数据。 对象属性被称为 实例变量成员字段。 实例变量是在类中定义的变量,类的每个对象都有一个单独的副本。

member_fields.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 是如何准确地连接到数据库的。 我们只知道它用于连接到数据库。 这对于划分编程中的责任至关重要,尤其是在大型应用程序中。

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 有三个访问修饰符:publicprotectedprivatepublic 成员可以从任何地方访问。 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 脚本中,我们有两个成员字段;一个声明为 public,另一个声明为 private。

$p->name = "Jane";
#$p->age = 17;

我们从外部世界访问 $name 成员。 通过外部世界,我们指的是“不在类中”。 这是可以的,因为 $name 变量被声明为 public。 访问 $age 成员是不可能的。 private 修饰符禁止这样做。 如果我们取消注释代码行,我们会得到“Fatal error: Cannot access private property 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

public 和 protected 成员被继承,private 成员不被继承。

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、宽度、高度。 如果 C++ 语言(Qt 的开发语言)没有方法重载,那么库的创建者将不得不将方法命名为 drawRectRectFdrawRectRectdrawRectXYWH。 使用方法重载的解决方案更优雅。

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 中不起作用。 运行此示例,我们得到以下错误:“Fatal error: Cannot redeclare Sum::getSum()”。 默认情况下,PHP 函数可以接受任意数量的变量。

为了在 PHP 中模拟方法重载,我们使用 func_get_args 函数。

overloading2.php
<?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(带两个下划线)。

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 8.0 中引入的一个特性,它允许您直接在构造函数参数列表中声明和初始化类属性。 这减少了样板代码,并使类定义更简洁。

promotion.php
<?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 能够创建类常量。 这些常量不属于具体对象。 它们属于类。 按照惯例,常量用大写字母书写。

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";

我们有一个 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 变量是否是某个类的实例化对象。

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";
    }
}

在上面的脚本中,我们有三个类:CatDogBird。 我们遍历数组,并为每个数组值打印类。

$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 方法

当我们对对象实例使用 printecho 关键字时,将调用 __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;

我们对它们使用 printecho 关键字。

$ 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

接下来是一个更复杂的示例。

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();

我们在这里使用了几个新概念。 在代码示例中,我们有三个类:BeingAnimalCatAnimal 类继承自 Being 类。 Cat 类继承自 Animal 类。 类继承未声明为私有的方法和数据成员。

abstract class Being {

Being 类被声明为 abstractabstract 关键字禁止实例化类。 创建 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,它是按钮小部件的抽象基类,提供按钮的公共功能。按钮 Q3ButtonQCheckBoxQPushButtonQRadioButtonQToolButton 继承自这个抽象基类。

正式来说,抽象类用于强制执行协议。协议是一组所有实现对象必须支持的操作。

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 {

CircleDrawing 类的子类。它必须实现抽象的 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 接口

遥控器是观众和电视之间的接口。它是此电子设备的接口。外交协议指导外交领域的所有活动。道路规则是驾驶者、骑自行车者和行人必须遵守的规则。编程中的接口与之前的例子类似。

接口是

对象通过它们暴露的方法与外界交互。实际的实现对程序员来说并不重要,或者它也可能是一个秘密。一家公司可能出售一个库,并且它不想公开实际的实现。程序员可能会在 GUI 工具包的窗口上调用一个 maximize 方法,但对该方法的实现方式一无所知。从这个角度来看,接口是对象与外界交互的方法,而无需过多地暴露其内部工作原理。

从第二个角度来看,接口是合同。如果达成一致,就必须遵守。它们用于设计应用程序的架构,并帮助组织代码。

接口是完全抽象的类型。它们使用 interface 关键字声明。接口只能有方法签名和常量。在接口中声明的所有方法签名都必须是公共的。它们不能有完全实现的方法,也不能有成员字段。一个 PHP 类可以实现任意数量的接口。一个接口也可以扩展任意数量的接口。实现接口的类必须实现接口的所有方法签名。

接口用于模拟多重继承。一个 PHP 类只能扩展一个类。一个 PHP 类可以实现多个接口。使用接口的多重继承不是关于继承方法和变量。它是关于继承思想或合同,这些思想或合同由接口描述。

接口和抽象类之间有一个重要的区别。抽象类为在继承层次结构中相关的类提供部分实现。另一方面,接口可以由彼此不相关的类实现。例如,我们有两个按钮:一个经典按钮和一个圆形按钮。两者都继承自一个抽象按钮类,该类为所有按钮提供一些公共功能。实现类是相关的,因为所有都是按钮。另一个例子可能有类 DatabaseSignIn。它们彼此无关。我们可以应用一个 ILoggable 接口,这将迫使它们创建一个用于进行日志记录的方法。

simple_interface.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

下一个示例展示了接口如何从多个其他接口扩展。

extending_interfaces.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 类。这个类变形为两个后代类:RectangleSquare。两者都提供了它们自己对 area 方法的实现。多态性为 OOP 系统带来了灵活性和可扩展性。

在本文中,我们介绍了 PHP 中的 OOP。

作者

我的名字是 Jan Bodnar,我是一位充满激情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。迄今为止,我撰写了超过 1,400 篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

来源

PHP 语言参考

列出所有 PHP 教程。