【问题标题】:php manual visibility example confusedphp手动可见性示例混淆
【发布时间】:2012-09-29 10:41:27
【问题描述】:

我对 php 手册中的示例感到困惑。这是关于能见度的。这是一个例子。

class Bar {
    public function test() {
        $this->testPrivate();
        $this->testPublic();
    }
    public function testPublic() {
        echo "Bar::testPublic\n";
    }
    private function testPrivate() {
        echo "Bar::testPrivate\n";
    }
}
class Foo extends Bar {
    public function testPublic() {
        echo "Foo::testPublic\n";
    }
    private function testPrivate() {
        echo "Foo::testPrivate\n";
    }
}
$myFoo = new foo();
$myFoo->test();  
?>

http://www.php.net/manual/en/language.oop5.visibility.php

这个例子输出

Bar::testPrivate 
Foo::testPublic

请您解释一下这是怎么发生的?

为什么两个testPublic() 都没有被调用?

我在 Bar 类构造中放置了一个 var_dump($this)。它打印object(Foo)[1]。我知道的是私有属性可以在同一个类中调用。

那么“Bar::testPrivate”是怎么调用的呢?

【问题讨论】:

    标签: php visibility


    【解决方案1】:

    那么“Bar::testPrivate”是怎么调用的呢?

    当您调用$myFoo->test() 时,它会在Bar 的上下文中运行代码,因为Foo 类没有覆盖它。

    Bar::test() 内部,当$this->testPrivate() 被调用时,解释器将首先查看Foo,但该方法是私有的(并且不能从Bar 调用来自后代类的私有方法),所以它继续上一级直到找到合适的方法;在本例中为Bar::testPrivate()

    相比之下,当$this->testPublic() 被调用时,解释器会立即在Foo 中找到合适的方法并运行它。

    编辑

    为什么两个 testPublic() 都没有被调用?

    当您运行$this->testPublic() 时,只有一个方法被调用,这是最远的一个(就与基类的距离而言)。

    如果Foo::testPublic() 还需要执行父级的实现,则应在该方法中写入parent::testPublic()

    【讨论】:

    • +1 为什么不能test()(即Bartest())调用FootestPrivate()?因为它是私密的,您不希望父母触碰孩子的隐私,对吗?
    • 我想,关于 testPublic() 的部分困惑是 PHP 会替换覆盖而不是细化覆盖。这意味着 PHP 不会在子级中调用父级的方法,除非您明确要求它这样做(例如:parent::testPublic();)。
    • @Jack 谢谢兄弟。你解释得很好。现在我可以理解重点了。因为 $this 指的是 foo,所以我认为应该调用 Foo 类的私有函数。这是我困惑的地方。
    【解决方案2】:

    您的函数位于Barclass 中,并且您正在使用神奇的$this 指针来调用成员函数。

    尝试将函数 test() 移动到 Foo 类,看看会发生什么。输出应为:

    Foo::testPrivate
    Foo::testPublic
    

    在您的示例中,调用了 Bar 的私有函数,因为它仅适用于该类。 Foo 类中没有 test 函数,因此 Bar 类中的测试函数无权调用它们。

    然后,由于函数重载,调用了类 Foo 的公共函数而不是 Bar 的公共函数。

    两个类都有同名的函数,所以子类的函数很重要。

    【讨论】:

      【解决方案3】:

      你打电话

      $myFoo->test();
      

      见函数test

      public function test() {
          $this->testPrivate();
          $this->testPublic();
      }
      

      当在 Bar 类(包括继承的类)的实例上调用它时,它会调用 testPrivatetestPublic

      这些方法在类Foo 中被覆盖,这意味着使用Foo 的方法。您可以随时调用基类的方法:

      // in Foo
      public function testPublic() {
          parent::testPublic();
          echo "Foo::testPublic\n";
      }    
      

      Bar::testPrivate 被调用是因为它是private 并且未被Foo::testPrivate 覆盖。

      查看更多herehere

      【讨论】:

        【解决方案4】:

        Private 并不意味着你不能调用它。这意味着您只能从 当前类 中调用它。 Public 表示您可以从任何类调用它。

        要拨打Bar::testPrivate,试试这个:

        $Bar->testPublic();
        

        parent::testPublic();
        

        但是,你不能调用$Bar->testPrivate(),因为方法是private

        【讨论】:

        • 这不能回答问题。
        • 抱歉,问题误解了。固定。
        【解决方案5】:

        我猜用户 'omega at 2093 dot es' (http://www.php.net/manual/en/language.oop5.visibility.php#109324) 的评论描述了同样的事情。 有人说:“在父类中定义的方法不能访问从它们继承的类中定义的私有方法。但是它们可以访问受保护的。”

        在您的情况下,Bar::test() 方法中的 $this 对象属于 Foo 类型(您的 var_dump 证明了这一点)。因为Foo::testPrivate()方法是私有的,所以不能从父类Bar访问,唯一可以访问的方法仍然是Bar::testPrivate()(尝试注释定义,你会得到致命错误)。这就是为什么第一个输出是Bar::testPrivate

        $this->testPublic(); 行调用Foo::testPublic() 方法,因为$thisFoo 类型并且方法被定义为public。

        简而言之,私有方法只能从定义它们的类中访问。它们既不能从子类也不能从父类访问。

        为了使方法可以从子类或父类访问,使其受到保护。例如,如果您要在两个类中保护 testPrivate() 方法,它将打印 Foo::testPrivate Foo::testPublic

        【讨论】:

          【解决方案6】:

          Foo 类扩展了 Bar 类。然后调用函数测试,它在 Bar 中定义。在这个函数中有两个调用。一个用于公共函数,一个用于 Bar 类中的私有函数。

          【讨论】:

            猜你喜欢
            • 2012-03-15
            • 2011-10-08
            • 2011-05-14
            • 1970-01-01
            • 2014-05-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多