在PHP中,类的受保护属性如何从静态方法可见?

在PHP中,类的受保护属性如何从静态方法可见?,php,class,oop,visibility,Php,Class,Oop,Visibility,我理解OOP。到目前为止,我所理解的是private和protected不能使用$this->blah符号从类外部引用。如果这是正确的,那么下面的代码如何工作 <?php class test { protected $a = "b"; public static function oo(){ $instance = new static(); echo $instance->a; } } test::oo(); 到目前为止,我的

我理解OOP。到目前为止,我所理解的是private和protected不能使用$this->blah符号从类外部引用。如果这是正确的,那么下面的代码如何工作

<?php

 class test {
   protected $a = "b";

   public static function oo(){
     $instance = new static();
     echo $instance->a;
   }
 }

 test::oo();

到目前为止,我的理解是private和protected不能从类外部引用


如下所示,由于
oo
的定义类型与
a
相同,
oo
可以访问
a

,这是因为您通过
echo
来“呈现”它。您不能像这样引用它,例如:

class test {
    private $a = 'b';

    function __construct() {
        echo 'instantiated';
    }
}

$test = new test();
echo $test->a; // This line won't work, since it's a private var.
它会给您一条如下所示的错误消息:

 class test {
   protected $a = "b";

   public static function oo(){
     $instance = new static();
     return $instance;
   }
 }

echo test::oo()->a;
致命错误:无法访问私有属性测试::$a


正如我前面所说,您是从类本身的中访问它的,因此您可以查看它。(这是您的
$instance
)如果您修改代码以如下方式使用它:

 class test {
   protected $a = "b";

   public static function oo(){
     $instance = new static();
     return $instance;
   }
 }

echo test::oo()->a;

你会犯“私人密码”之类的错误


你理解错了
“private和protected不能从类外引用”
意味着,正如上面的示例所示,您不能访问类外的变量,但对于您的示例,您是从类内访问变量,这意味着它们将按照您的要求执行(
echo
'ing out as you do)

在PHP 5.3中,添加了一个称为后期静态绑定的新特性,这可以帮助我们获得在这种情况下可能更可取的多态行为。最简单地说,后期静态绑定意味着对继承的静态函数的调用将在运行时“绑定”到调用类。因此,如果我们使用后期静态绑定,这意味着当我们调用“test::oo();”时,将调用test类中的oo()函数;static关键字允许函数在运行时绑定到调用类。因此,如果您使用static,那么无论您使用什么访问修饰符(private、public、protected),它的意义都会更小


请阅读这篇文章,

这实际上是一个很好的问题,不应该被否决

据我所知,之所以可以从同一类的静态方法中访问受保护/私有属性,是因为“在这个类中,特定于实现的细节已经知道了”。我将这一点从官方页面上关于可见性的记录中稍作修改:

相同类型的对象将有权访问彼此的私有成员和受保护成员,即使它们不是相同的实例。这是因为在这些对象中,特定于实现的细节是已知的


这是有道理的。可见性访问旨在仅公开对公众安全使用的内容。但是,如果您已经可以访问正在使用的类的代码,那么就没有必要阻止您使用已经看到的代码。希望这是有意义的。

绝对不是。OO没有对a的显式访问。这怎么可能?由于oo是一个静态函数,它无法读取非静态属性,而不提供任何类实例。@ChristianM.Raymonds您将“类”与“类实例”混淆了。在您的示例中,这两个方法都在同一个类中定义,尽管将对该类的实例调用
a
,并且将在没有实例的情况下调用
oo
(因为它是静态的)。不过,它们是在同一个类中定义的。现在,我对PHP不太熟悉,但这种行为在大多数(如果不是所有)编程语言中都很常见。看看这个简单的C#示例:好的,告诉我,你是说因为静态函数是在类中定义的,所以它可以读取类属性吗?静态上下文:不绑定到类的实例,而是绑定到类本身。再说一次,纯粹主义者可能会认为OO中的静态上下文是一种令人憎恶的东西。我不明白你的答案。首先,静态函数不知道非静态类变量,因为$this范围不可用,对吗?因此,我以$instance=new class()的形式给了它一个实例;现在,如何使用$instance->var访问这个$instance的私有变量?您正在从类本身中访问它,因为它是自身的实例,所以它可以轻松访问
$a
变量。查看最新的示例(在我的编辑中)检查我对代码的更新,当我向其提供对象本身时,它仍然无法读取属性。哈哈,您上次的编辑很有趣:P您说如果我执行echo test::oo()->a;我会得到那个错误??您是否尝试过这个var_导出(test::oo())??它包含属性:D。函数结果体被序列化,在PHP中它们被视为数组!是 啊但是我得到了答案,非常感谢!在@Rajib之后,我认为这一切都是有意义的。现在,我明白你说的了!谢谢你,朋友!它认为您的主要问题是:类外部与实例化对象外部不同。这是有区别的。@Wrikken+1,我的观点正是如此。因此,如果您使用静态,那么无论您使用什么访问修饰符(私有、公共、受保护),它的意义都会更小。。。魔术测试过了,你的解释是正确的!谢谢你,伙计!这毫无意义。从这些链接中,“从PHP5.3.0开始,PHP实现了一个称为后期静态绑定的特性,可用于在静态继承上下文中引用被调用的类”——这里没有继承。这些链接上的示例与OP的示例无关。“这可以帮助我们获得多态行为”-什么多态行为?这与“后期静态绑定”无关-这是一个简单的OOP问题。我想首先你必须知道变量作用域这与作用域也无关。变量的范围是它的生存期。这与
的生命周期无关。你知道你什么时候给sta打电话吗