类与对象
PHP 类是一个包含代码的文件。类文件是一个实际存在于硬盘上的文件。如果你关掉电脑,然后再打开,类文件仍然存在。它包含的代码是在执行过程中创建对象的模板。类文件可以包含属性和行为。一旦类被实例化,属性就能在内存中保存数据。行为将由方法或函数处理。您可以使用访问器和突变器方法来更改类的属性值。
<?php
namespace Animal;
class Dog
{
public function returnSound(): string
{
return "Bark";
}
}
前面的示例类是一个 PHP 文件,其中包含命名空间声明、类名和一个名为 returnSound()
的方法或函数,该方法或函数返回一个 "Bark"
字符串。
另一方面,对象是类文件的实例。该对象物理上存在于计算机的 RAM 中,这是易失性存储器。这意味着如果您关闭计算机或停止程序,您就会丢失该对象。仅当您运行程序时才会创建该对象。
在 PHP 中,当您执行程序时,PHP 将从硬盘加载类文件,以创建临时存在于 RAM 中的对象实例。从字面上看,类是 PHP 在程序运行时创建对象的模板。
我们将使用一个消费者类来利用或使用 Dog.php
类,并使用一个变量来保存类的实例,该实例是一个对象:
<?php
namespace Animal;
class Display
{
public function outputSound()
{
$dog = new Dog();
echo $dog->returnSound();
}
}
Display
类是另一个类,可以将其视为消费者类或示例程序的起点。在这个类中,我们有一个 outputSound()
方法,用于 echo
对象的 returnSound()
方法的返回值。在 outputSound()
方法中,我们编写了 PHP 使用 new
关键字创建 Dog
类实例的指令:

当 PHP 执行 outputSound()
方法时,它将根据存储在计算机驱动器中的 Dog.php
类文件创建一个对象,然后将该实例或对象暂时存储在计算机内存中。$dog
变量将与 Dog
类实例或对象进行映射。无论何时使用对象的方法或属性,基本上都是从电脑内存而非 Dog.php
类文件访问对象。要进一步理解这一点,我们需要讨论一下 PHP 中的引用(References),这将在下一个小节中介绍。
现在,既然我们已经创建了一个 Dog.php
类文件的新实例并将其赋值给 $dog
变量,我们就可以访问 Dog
对象的方法、函数或属性了,这取决于它们的可见性。我们将在本章的 "OOP 中的封装" 部分讨论可见性。在我们的示例中,Dog.php
类的 returnSound()
方法被定义为 public
,因此我们可以通过 Display.php
类的 outputSound()
方法访问该方法:$dog->returnSound();
。
PHP 中的引用和对象
引用到底是什么?在 PHP 中,它是一个别名,或者说是一个或多个变量指向特定内容的一种方式。在前面的 Dog
对象示例中,我们创建了一个 Dog.php
类的实例,并将其赋值给 $dog
变量。$dog
变量本身并不包含 Dog
对象或实例的内存地址;它只是包含一个标识符,以便指向存储在内存中的 Dog
对象。也就是说,你可以让 $dog1
和 $dog2
变量指向同一个对象。让我们修改 Dog.php
和 Display.php
类来演示这一概念。
我们将这样修改 Dog.php
类
<?php
namespace Animal;
class Dog
{
private string $sound;
public function __construct()
{
$this->setSound("Bark");
}
public function returnSound(): string
{
return $this->getSound();
}
/**
* @return string
*/
public function getSound(): string
{
return $this->sound;
}
/**
* @param string $sound
*/
public function setSound(string $sound): void
{
$this->sound = $sound;
}
}
我们将修改 Display.php
类如下:
<?php
namespace Animal;
class Display
{
public function outputSound()
{
$dog1 = new Dog();
$dog2 = $dog1;
$dog1->setSound("Barky Bark");
// Will return "Barky Bark" which was set to $dog1.
echo $dog2->returnSound();
}
}
我们修改了 Dog.php
类,以便我们可以在实例化它后更改它返回的声音。在 Display.php
类中,您会注意到我们引入了一个新变量 $dog2
,并为其分配了 $dog1
。我们只有一个 Dog
对象实例,并且 $dog1
和 $dog2
变量具有相同的标识符并且引用相同的事物。这是代表这个概念的图表:

因此,如果我们运行 $dog2->returnSound()
,它将返回我们在 $dog1
中设置的更新后的字符串,即使我们在将 $dog1
分配给 $dog2
后更改了 $sound
属性。
那么,如果您不希望 $dog2
受到 $dog1
属性发生的影响,但仍想创建该对象的副本或副本,该怎么办? 您可以像这样使用 PHP 的 clone
关键字:
<?php
namespace Animal;
class Display
{
public function outputSound()
{
$dog1 = new Dog();
$dog2 = clone $dog1;
$dog1->setSound("Barky Bark");
// Will return "Bark".
echo $dog2->returnSound();
}
}
这次,$dog2
将返回由其构造函数分配给 $dog1
的 $sound
属性的原始 Bark
字符串值。这是一个图表供您参考以理解这一点:

由于 $dog2
在 actor 改变 $dog1
的 $sound
属性之前就已被克隆,因此 $dog2
将保留旧值。无论 $dog1
发生什么,$dog2
都不会再自动发生,因为它们不再引用内存中的同一个对象:

总之,PHP 类是一个包含 PHP 能够创建对象的模板的文件。当使用 new
关键字并执行时,PHP 获取 class
文件并生成 class
文件的实例,并将其存储在计算机的内存中,这就是我们所说的对象。
现在我们已经阐明并解释了 PHP 中对象和类之间的区别,现在我们可以从抽象开始讨论 OOP 的四大支柱。