在类外部访问受保护的成员变量

17

我正在通过访问一个已经存在的类函数来查询一个字段的ID。结果是返回一个包含受保护成员变量的对象。我很难看到如何在类外部访问成员变量的值。


你使用的是哪种编程语言? - Adrian Regan
https://dev59.com/f2Qn5IYBdhLWcg3wAjIY#70462175 - pankaj
8个回答

25

访问公共属性或方法中的受保护或私有变量是不正确的(这就是它们被定义为受保护或私有的原因)。更好的方法是扩展类并访问所需的属性或创建getter方法以使其公开。但如果您仍然想在不扩展类的情况下获取属性,并且正在使用PHP 5,则可以使用Reflection类来访问。实际上,尝试使用ReflectionProperty类。

class Foo { protected $bar; }
$foo = new Foo();

$rp = new ReflectionProperty('Foo', 'bar');
$rp->setAccessible(true);
echo $rp->getValue($foo);

4
ReflectionProperty 对我很有用。但是不要忘记调用 ReflectionProperty::setAccessible(true) - Asaph
这是正确的答案。请注意,ReflectionProperty 的第一个参数必须是完全命名空间的类。 - Aaron Averill
这真的很有用,这是我如何实现它的。$client = new Client($sid, $token); $rp = new ReflectionProperty($client, 'environment'); $rp->setAccessible(true); $environment = $rp->getValue($client); - Awais Jameel

20

以下是正确的答案:

我们可以使用Closure类的bind()或bindTo()方法来访问某个类的私有/受保护数据,例如:

class MyClass {
          protected $variable = 'I am protected variable!';
}

$closure = function() {
          return $this->variable;
};

$result = Closure::bind($closure, new MyClass(), 'MyClass');
echo $result(); // I am protected variable!

4
哇!太漂亮了。为什么这个没有更多的投票? - CenterOrbit

19

只需在该类中添加一个“get”方法即可。

class Foo
{
    protected $bar = 'Hello World!';

    public function getBar()
    {
        return $this->bar;
    }
}

$baz = new Foo();

echo $baz->getBar();

显然,我们已经有了一个可以让我简单地使用->getId()并从各种类中检索的方法。 - user275074

4

您可以在类外访问受保护的类成员,而且不需要扩展受保护成员类,也不需要使用任何受保护成员类的函数。使用下面的函数来访问它。

function getProtectedMember($class_object,$protected_member) {
     $array = (array)$class_object;      //Object typecast into (associative) array
     $prefix = chr(0).’*’.chr(0);           //Prefix which is prefixed to protected member
     return $array[$prefix.$protected_member];
}

请访问链接,以获取更多有关此事的详细信息。

4
我很困惑如何在类外访问成员变量的值。
你无法这样做:这就是“protected”的目的。
你需要使用extend类并创建一个方法来获取变量的值。
但是你不能在已实例化的对象上这样做,你必须影响类定义或更改创建对象时的类。

1

例如,使用闭包访问PHP中的受保护变量

class ForExample
{
    protected $var=122;
}



$call=function(){

    echo $this->var;
};

$call->call(new ForExample());

太棒了,它完美地处理了受保护变量。 - Harsh Patel
1
它适用于私有的、受保护的和公共的。 - dılo sürücü

0

如果你真的需要那个值:

  • 修改类并添加一个公共方法来返回你想要的值。
  • 如果你不能修改它,考虑扩展它并在那里公开该值(因为它是受保护的,所以可以访问)。更喜欢第一种选项,这更像是一个hack。

显然,类设计者认为你不需要访问你正在尝试访问的值,否则他会自己添加一个检索方法。因此,请重新考虑你正在做什么。


-3

免责声明:我不记得如何编码了。已经“有一段时间”了。这可能完全不正确。

首先,如果成员受到保护,原始设计者并不打算让您直接访问它们。您是否检查了访问器方法?

如果没有,而且您确信确实需要这些受保护的成员,您可以使用访问器扩展类型、转换并以此方式获取它们。例如(在类似C++的代码中)

class MyClass : public OldClass
{
public:
int getSomeValue() { return protectedValue; }
void setSomeValue(int value) { protectedValue=value; }
char* getOtherValue() { return otherProtectedValue; }
}

然后使用它

MyClass* blah = (MyClass*)TheirFactory->GiveMeAClass();
int yay=blah->getSomeValue();

你明白的。希望对你有用,Internet Explorer 不太适合编译器,所以我无法测试它。


1
这很好,但是OP需要一个PHP解决方案 :) - Pekka
1
好的,我会假设PHP支持继承和类型转换,并且希望他能够理解C++代码并在PHP中实现它 :) - Tobias
1
显然我们已经有了一个可以让我简单使用->getId()并从各种类中检索的方法。-用户275074而唯一得分为负的答案是建议寻找访问器的答案,而替代方案并没有让我感到违反 :D - Tobias

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接