PHP - 访问修饰符
在 PHP 中,关键字 public、private 和 protected 被称为 访问修饰符。这些关键字控制 class 属性和方法的访问范围或可见性。在声明成员变量和定义成员函数时,需要在前面加上这些关键字之一。
PHP 中的访问修饰符
PHP 代码是否可以自由访问 class 成员、是否被限制访问,或者是否具有条件访问,由这些关键字决定 —
Public − class 成员可以从任何地方访问,即使是在 class 作用域外部,但必须通过对象引用。
Private − class 成员只能在 class 内部访问。它防止 class 外部通过 class 实例引用访问成员。
Protected − 成员只能在 class 及其子 class 中访问,其他地方均不可访问。
数据封装原则是面向对象编程方法论的基石。它指的是将对象的数据成员或属性与 class 外部环境隔离的机制,只允许通过 class 中提供的方法或函数进行受控访问。
面向对象编程中的访问控制
为了实现封装,class 的数据成员被设置为 private,而方法被设置为 public。
上图展示了面向对象编程中访问修饰符的使用,主要说明了 public 和 private 成员如何与 class 外部代码交互。
Private 数据成员只能在 class 内部访问。红色“X”表示 class 外部代码无法直接访问私有成员。
Public 函数可以通过对象引用从 class 外部访问。Public 函数通常用于安全地访问 private 数据。
显然,private 属性如何对外部世界隐藏,这实现了封装,这是 OOP 的基本原则之一。
Public 成员
在 PHP 中,class 成员(包括成员变量和成员函数)默认都是 public。
示例
在下面的程序中,对象的成员变量 title 和 price 在 class 外部可以自由访问,因为它们默认是 public,除非另有指定。
<?php
class Book {
/* 成员变量 */
var $price;
var $title;
/*构造函数*/
function __construct(string $param1="PHP Basics", int $param2=380) {
$this->title = $param1;
$this->price = $param2;
}
function getPrice() {
echo "Title: $this->price \n";
}
function getTitle() {
echo "Price: $this->title \n";
}
}
$b1 = new Book();
echo "Title : $b1->title Price: $b1->price";
?>
它将产生以下 输出 —
Title : PHP Basics Price: 380
私有成员
如上所述,封装原则要求成员变量不能直接访问。只有方法才能访问数据成员。因此,我们需要将成员变量设置为 private,方法设置为 public。
<?php
class Book {
/* 成员变量 */
private $price;
private $title;
/*构造方法*/
function __construct(string $param1="PHP Basics", int $param2=380) {
$this->title = $param1;
$this->price = $param2;
}
public function getPrice() {
echo "Price: $this->price \n";
}
public function getTitle() {
echo "Title: $this->title \n;";
}
}
$b1 = new Book();
$b1->getTitle();
$b1->getPrice();
echo "Title : $b1->title Price: $b1->price";
?>
输出
现在,getTitle() 和 getPrice() 函数是 public 的,可以访问私有成员变量 title 和 price。但是,在尝试直接显示 title 和 price 时,会遇到错误,因为它们不是 public 的。
Title: PHP Basics Price: 380 Fatal error: Uncaught Error: Cannot access private property Book::$title in hello.php:31
受保护成员
为类成员指定 protected 访问权限的效果在类继承的情况下才会显现。我们知道,public 成员可以从类外部的任何地方访问,而 private 成员则被拒绝从类外部的任何地方访问。
protected 关键字允许同一类对象及其继承类的对象访问,拒绝其他环境访问。
让我们在 Book 类示例中将 title 成员设置为 protected,price 保持为 private。
class Book {
/* 成员变量 */
private $price;
protected $title;
# 其余代码保持不变
}
$b1 = new Book();
$b1->getTitle();
$b1->getPrice();
PHP 允许访问这两个成员变量,因为对象属于同一类。
让我们添加一个 mybook 类,它继承 Book 类 −
class mybook extends Book {
# 未定义额外成员
}
它的对象仍然能够访问成员变量,因为子类继承了父类的 public 和 protected 成员。
然而,将 mybook 类作为独立类(不继承 Book 类)并定义一个 getmytitle() 函数,该函数试图访问 Book 类的 protected title 成员变量。
class mybook {
public function getmytitle($b) {
echo "Title: $b->title <br/>";
}
}
$b1 = new mybook();
$b = new Book();
$b1->getmytitle($b);
由于 getmytitle() 函数试图打印 Book 对象的 title,会引发错误信息 Cannot access protected property Book::$title。
示例
尝试运行以下代码 −
<?php
class Book {
private $price;
protected $title;
function __construct(string $param1="PHP Basics", int $param2=380) {
$this->title = $param1;
$this->price = $param2;
}
public function getPrice(){
echo "Price: $this->price <br/>";
}
public function getTitle(){
echo "Title: $this->title <br/>";
}
}
class mybook {
public function getmytitle($b) {
echo "Title: $b->title <br/>";
}
}
$b1 = new mybook();
$b = new Book();
$b1->getmytitle($b);
?>
它将产生以下 输出 −
PHP Fatal error: Uncaught Error: Cannot access protected property Book::$title in /home/cg/root/97848/main.php:18
因此,可以看出,受保护成员仅能被同一类对象和继承类对象访问。对于所有其他环境,受保护成员不可访问。
访问规则
访问规则可以由下表总结 −
