php 中是否有相当于“朋友”或“内部”的东西?如果没有,是否有任何模式可以遵循来实现这种行为?
编辑: 抱歉,但标准 Php 不是我想要的。我正在寻找与马戏团长所做的类似的东西。
我有一些类在后端进行 C 风格的系统调用,并且杂耍已经开始变得很麻烦。我在对象 A 中有函数,它接受对象 B 作为参数,并且必须调用对象 B 中的方法,将其自身作为参数传递。最终用户可以调用 B 中的方法,系统就会崩溃。
PHP 不支持任何类似友元的声明。可以使用 PHP5 __get 和 __set 方法来模拟这一点,并仅检查允许的友元类的回溯,尽管执行此操作的代码有点笨拙。
PHP 网站上有一些 示例代码 和有关该主题的讨论:
class HasFriends
{
private $__friends = array('MyFriend', 'OtherFriend');
public function __get($key)
{
$trace = debug_backtrace();
if(isset($trace[1]['class']) && in_array($trace[1]['class'], $this->__friends)) {
return $this->$key;
}
// normal __get() code here
trigger_error('Cannot access private property ' . __CLASS__ . '::$' . $key, E_USER_ERROR);
}
public function __set($key, $value)
{
$trace = debug_backtrace();
if(isset($trace[1]['class']) && in_array($trace[1]['class'], $this->__friends)) {
return $this->$key = $value;
}
// normal __set() code here
trigger_error('Cannot access private property ' . __CLASS__ . '::$' . $key, E_USER_ERROR);
}
}
(代码由 tsteiner 在 nerdclub dot net 在 bugs.php.net 上证明)
还可以在 php >=5.3.3 中使用握手和闭包来提升权限,也称为选择性泄漏数据。
基本上,交互是这样的:类 A 有一个公共方法,它接受类 B 对象,并调用 B->grantAccess (或您的接口定义的任何内容),向其传递一个闭包。闭包
use($that,$anythingelseyouneed)
其中 $that=$this,以及确定允许访问哪些属性所需的任何其他内容。闭包有一个参数 - 要返回的属性;如果它是 $that 上的一个属性并且一切都很酷,则闭包将返回该属性。否则,它返回 '',或者抛出异常,或者可能是默认值。
B 类->grantAccess 接受一个可调用对象并存储它,在其他方法中使用它来提取闭包允许泄漏的私有属性。将 B 类的默认构造函数设为私有。使用采用 A 类参数的静态工厂方法构造 B,以确保握手发生。
也许这个?只是一个 hack,不是 C++ 中真正的朋友关键字,在这种情况下仅适用于构造函数...
<?php
class FooWithFriend {
private function guardOnlyFriend(): void
{
if (( is_a($this, BarFriendOfFoo::class) ) === false ) {
throw new Exception('Only class BarFriendOfFoo he can create me');
}
}
protected function __construct()
{
$this->guardOnlyFriend();
echo 'Hello friend - ';
}
}
final class BarFriendOfFoo extends FooWithFriend {
public function __construct()
{
parent::__construct();
}
}
final class Bar2FriendOfFoo extends FooWithFriend {
public function __construct()
{
parent::__construct();
}
}
$bar = new BarFriendOfFoo();
$bar = new Bar2FriendOfFoo();
$dummy = new FooWithFriend();
该语言不支持。有多种不同的方法可以近似它,具体取决于您的目标是什么。如果您只是想弄清楚预期调用的内容(例如,避免在 IDE 中自动完成用户不应该使用的方法),您可以使用更窄的接口或父类来键入对象:
abstract class Entity {
protected $value = null;
public function getValue() { return $this->value; }
}
class MutableEntity extends Entity {
public function setValue( $value ) { $this->value = $value; }
}
function getEntity(): Entity {
// returns a MutableEntity but says it's an Entity so
// the IDE will not offer setValue()
return new MutableEntity();
}
如果您确实想强制执行访问限制,您可能必须使用闭包。但是,恶意用户可以使用反射轻松解决任何访问限制,因此没有太多尝试强制执行它。
我很确定您正在寻找的是“受保护”或“私有”,具体取决于您的用例。
如果您在类中定义函数,并且只希望它可供自身使用,则可以这样定义它:
private function foo($arg1, $arg2) { /*function stuff goes here */ }
如果您在类中定义一个函数,希望该函数可供从该类继承的类使用,但不能公开使用,请这样定义:
protected function foo($arg1, $arg2)
我非常确定,默认情况下,在 PHP5 中,函数是公共的,这意味着您不必使用以下语法,但它是可选的:
public function foo($arg1, $arg2) { /*function stuff goes here */ }
在使用公共函数之前,您仍然必须实例化该对象。因此,我将彻底告诉您,为了在类中使用函数而不实例化对象,请务必使用以下语法:
static function foo($arg1, $arg2) { /*function stuff goes here */ }
这将允许您仅通过引用类来使用该函数,如下所示:
MyClass::foo($a1, $a2);
否则,您需要执行以下操作:
$myObject = new MyClass();
$myObject->foo($a1, $a2);