为什么可以通过引用从外部 class 访问私有变量?
Why is it possible to access private variables from outside class by reference?
如果我有一个 public class 方法返回对不可见(私有或受保护)的引用 属性,我可以使用该引用来获得直接访问:
PHP代码
class A
{
private $property = 'orange';
public function &ExposeProperty()
{
return $this->property;
}
public function Output()
{
echo $this->property;
}
}
$obj = new A();
# prints 'orange'
$obj->Output();
$var = &$obj->ExposeProperty();
$var = 'apple';
# prints 'apple'
$obj->Output();
PHP 中的此功能背后是否有原因?或者它只是一个设计疏忽,未能通过引用跟踪访问违规?
当您想要实现以下目标时,它显然会派上用场:
PHP代码
$this->load->resource();
其中 load
是修改 $this
给定属性的对象。但是除了这个快捷方式之外,我没有看到很多可能的用途,否则就无法使用有效的 OOP 模式。
好吧,您是明确return引用一个值。你锁上了前门,但随后打开了一个侧门。你是非常故意在这里瞄准自己的脚。如果 $property
是一个对象,并且您 return 这个对象有或没有 &
引用,对该对象的任何修改也会反映在 $property
上。这就是 reference 的工作原理,它总是修改引用指向的唯一一个现有值。
能见度修饰符不是万能的"protections"。有许多方法可以绕过 private
可见性来访问和修改 属性。它们主要作为您自己和其他开发人员的标志,表明 不应直接访问此 属性,它仅供内部使用,而不是 publicly 批准的 API . 并且 PHP 如果您忘记了这一点,将会打您的手腕。不多也不少。
此外,这里并没有真正违反任何内容。外部代码绝不会访问或修改 $obj->property
。这是 private
唯一应该禁止的事情。您实际上是在修改 private
属性 的对象上公开 public API。通常这是通过 getter 和 setter 函数完成的,但是通过引用 API 显然也可以。
如果我有一个 public class 方法返回对不可见(私有或受保护)的引用 属性,我可以使用该引用来获得直接访问:
PHP代码
class A
{
private $property = 'orange';
public function &ExposeProperty()
{
return $this->property;
}
public function Output()
{
echo $this->property;
}
}
$obj = new A();
# prints 'orange'
$obj->Output();
$var = &$obj->ExposeProperty();
$var = 'apple';
# prints 'apple'
$obj->Output();
PHP 中的此功能背后是否有原因?或者它只是一个设计疏忽,未能通过引用跟踪访问违规?
当您想要实现以下目标时,它显然会派上用场:
PHP代码
$this->load->resource();
其中 load
是修改 $this
给定属性的对象。但是除了这个快捷方式之外,我没有看到很多可能的用途,否则就无法使用有效的 OOP 模式。
好吧,您是明确return引用一个值。你锁上了前门,但随后打开了一个侧门。你是非常故意在这里瞄准自己的脚。如果 $property
是一个对象,并且您 return 这个对象有或没有 &
引用,对该对象的任何修改也会反映在 $property
上。这就是 reference 的工作原理,它总是修改引用指向的唯一一个现有值。
能见度修饰符不是万能的"protections"。有许多方法可以绕过 private
可见性来访问和修改 属性。它们主要作为您自己和其他开发人员的标志,表明 不应直接访问此 属性,它仅供内部使用,而不是 publicly 批准的 API . 并且 PHP 如果您忘记了这一点,将会打您的手腕。不多也不少。
此外,这里并没有真正违反任何内容。外部代码绝不会访问或修改 $obj->property
。这是 private
唯一应该禁止的事情。您实际上是在修改 private
属性 的对象上公开 public API。通常这是通过 getter 和 setter 函数完成的,但是通过引用 API 显然也可以。