【问题标题】:How can protected property of a class be visible from a static method in PHP?如何从 PHP 中的静态方法中看到类的受保护属性?
【发布时间】:2015-01-24 04:23:25
【问题描述】:

我了解面向对象编程。到目前为止我所理解的是,不能使用 $this->blah 表示法从类外部引用私有和受保护。如果正确,下面的代码如何工作?

<?php

 class test {
   protected $a = "b";

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

 test::oo();

给我一​​个 b 的输出!现在,以上帝的名义怎么会发生这种情况?

【问题讨论】:

  • 它认为你的主要问题是:类外与实例化对象外不一样。有区别。
  • @Wrikken +1,我的观点完全正确。

标签: php class oop visibility


【解决方案1】:

到目前为止我的理解是私有和受保护不能从类外部引用

如下,由于ooa定义为同一类型,所以oo可以访问a

【讨论】:

  • 绝对不是。 OO 没有显式访问 a.这个怎么可能?因为 oo 是一个静态函数,它不能在没有任何类实例的情况下读取非静态属性。
  • @ChristianM.Raymonds 您将“类”与“类的实例”混淆了。在您的示例中,两种方法都定义在同一个类中,尽管 a 将在该类的实例 $instance 上调用,而 oo 将在没有实例的情况下调用(因为它是静态的)。然而,它们在同一类中定义
  • 现在,我对 PHP 并不熟悉,但这种行为对于大多数(如果不是全部)编程语言都很常见。看看这个简单的 C# 示例:dotnetfiddle.net/wxUAZA
  • 好吧,告诉我一些事情,你是说既然类中定义了静态函数,它就可以读取类属性?
  • 静态上下文:不绑定到类的实例,而是绑定到类本身。再一次,纯粹主义者可能会争辩说 OO 中的静态上下文是可憎的。
【解决方案2】:

这是因为您通过echo'ing 来“展示”它。例如,您不能像这样引用它:

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.

它会给你一个如下所示的错误消息:

致命错误:无法访问私有财产 test::$a

Example (https://eval.in/226435)


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

 class test {
   protected $a = "b";

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

echo test::oo()->a;

Example of the above (https://eval.in/226439)

您将收到“私人访问等等”错误。

您对陈述的理解是错误的。 "private and protected cannot be referenced from outside the class" 表示如上面的示例所示,您不能访问类外部的变量,但在您的示例中,您可以从类内部访问它,这意味着它们会按照您的要求执行 (echo'像你一样出去)

【讨论】:

  • 我不明白你的回答。首先,静态函数不知道非静态类变量,因为 $this 范围不可用,对吧?所以,我以 $instance = new class(); 的形式给了它一个实例。现在,如何使用 $instance->var 访问此 $instance 的私有 var ??
  • 您从类本身中访问它,并且由于它是自身的一个实例,它可以轻松访问$a 变量。查看最新示例(在我的编辑中)
  • eval.in/226451 检查我对代码的更新,当我给它提供一个自身的对象时,它仍然无法读取该属性。
  • 哈哈,你上次的编辑很有趣:P 你说如果我做 echo test::oo()->a;我会得到那个错误??你试过这个 var_export(test::oo()) 吗?它包含属性:D。函数结果体被序列化,在 PHP 中它们被视为数组!
  • 是的.. 但我得到了答案,非常感谢!在@Rajib 之后,我认为这一切都说得通。现在,我明白你在说什么了!非常感谢朋友!
【解决方案3】:

在 PHP 5.3 中,添加了一个称为后期静态绑定的新功能 - 这可以帮助我们获得在这种情况下可能更可取的多态行为。简单来说,后期静态绑定意味着对继承的静态函数的调用将在运行时“绑定”到调用类。因此,如果我们使用后期静态绑定,这意味着当我们调用“test::oo();”时,将调用测试类中的 oo() 函数。之后返回 $instance->一种; static 关键字允许函数在运行时绑定到调用类。因此,如果您使用静态,那么您使用的任何访问修饰符(私有、公共、受保护)都意味着更少...

请阅读此link,another

【讨论】:

  • 因此,如果您使用静态,那么无论您使用什么访问修饰符(私有、公共、受保护),它的意义都会减少…… 魔术! eval.in/226466 测试过,你的解释是正确的!谢谢老哥!
  • 这没有任何意义。从这些链接中,“从 PHP 5.3.0 开始,PHP 实现了一个称为后期静态绑定的功能,可用于在静态继承的上下文中引用被调用的类”——这里没有继承。这些链接上的示例与 OP 的示例无关。 “这可以帮助我们获得多态行为” - 什么多态行为?这与“后期静态绑定”无关——这是一个简单的 OOP 问题。
  • 我认为首先你必须知道变量范围
  • 这也与作用域无关。变量的范围是它的生命周期。这与a 的生命周期无关。完全没有。
  • 你知道当你调用静态时会发生什么:)
【解决方案4】:

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

据我了解,您可以从同一类的静态方法中访问受保护/私有属性的原因是“在此类内部已经知道实现特定的细节”。我根据 Visibility 官方页面上记录的内容稍微改写了这一点:

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

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

【讨论】:

    猜你喜欢
    • 2013-10-02
    • 2016-02-19
    • 2011-06-06
    • 1970-01-01
    • 2020-03-31
    • 2016-02-18
    • 2014-12-19
    • 1970-01-01
    • 2011-05-25
    相关资源
    最近更新 更多