什么是`protected`在PHP中意味着什么?

时间:2013-10-21 13:53:30

标签: php inheritance siblings

我正在阅读一些PHP代码,我注意到一个类在其兄弟上调用受保护的方法(继承自普通父代)。这让我感到反直觉。

PHP中的in the same inheritance tree是否意味着like Java's part of the same package

I'm more used to the C# meaning of protected.

因为我更习惯于C#的protected的含义,所以我没想到能够在兄弟类上调用受保护的方法。在Java中,包的区别很明显。除了继承之外,还有什么能在PHP中定义此实例中的可访问性吗?

<?

class C1
{
    protected function f()
    {
        echo "c1\n";
    }
}

class C2 extends C1
{
    protected function f()
    {
        echo "c2\n";
    }
}

class C3 extends C1
{
    public function f()
    {
        // Calling protected method on parent.
        $c1 = new C1();
        $c1 -> f();

        // Calling protected method on sibling??!?
        $c2 = new C2();
        $c2 -> f();

        echo "c3\n";
    }
}

$c3 = new C3();
$c3 -> f();

// OUTPUT:
// c1
// c2
// c3

这是我在C#中尝试同样的事情(并且失败了)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class c1
    {
        protected void f()
        {
            Console.WriteLine("c1");
        }
    }
    class c2: c1
    {
        protected void f()
        {
            Console.WriteLine("c2");
        }
        public void g()
        {
            Console.WriteLine("g!");
        }
    }

    class c3 : c1
    {
        protected void f()
        {
            // Error    1   Cannot access protected member 'ConsoleApplication2.c1.f()' 
            //  via a qualifier of type 'ConsoleApplication2.c1'; the qualifier must be 
            // of type 'ConsoleApplication2.c3' (or derived from it)    
            //c1 cone = new c1();
            //cone.f();

            base.f();

            c2 ctwo = new c2();
            //Error 1   'ConsoleApplication2.c2.f()' is inaccessible due to its protection level
            ctwo.f();
            ctwo.g();


            Console.WriteLine("c3");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            c3 cthree = new c3();
            // Error    2   'ConsoleApplication2.c3.f()' is inaccessible due to its protection level
            cthree.f();
        }
    }
}

看起来预期的行为就是PHP 5.2之前的情况。 This RFC explains the issue a little more,并指向why the change happened in this bug

我不确定它是否完全回答了我的问题,但我想我会更新这个问题,万一它可以帮助任何人。

感谢Robin F.,pointing me to this discussion of the RFC,感谢某些背景。

3 个答案:

答案 0 :(得分:1)

对我而言,没有任何乱序。 protected表示此类及其所有子类都可见。

让我们分析一下这个片段

class C3 extends C1
{
  public function f()
  {
    // Calling protected method on parent.
    $c1 = new C1();
    $c1 -> f();

    // Calling protected method on sibling??!?
    $c2 = new C2();
    $c2 -> f();

    echo "c3\n";
  }
}

你正在覆盖C1->f() [这没关系]但是第一次回忆$c1->f()(因为$c1C1类的实例)所以输出完全没问题。
第二次你打电话给$c2->f()所以没有兄弟功能,但C2类功能,这是完全合法的,因为你也覆盖了它。

也许我不能正确理解你的问题,但这是对上述代码片段的解释

答案 1 :(得分:0)

看起来预期的行为就是PHP 5.2之前的情况。 This RFC explains the issue a little more,并指向why the change happened in this bug

我不确定它是否能完全回答我的问题,但我认为我会更新问题,以防万一。

感谢Robin F.,pointing me to this discussion of the RFC,感谢某些背景。

答案 2 :(得分:-1)

根据维基百科(http://en.wikipedia.org/wiki/Php):

  

相同类型的对象可以访问彼此的私有成员和受保护成员,即使它们不是同一个实例。

修改

请参阅代码段(在 Java 中):

public class SimpleApp {

    public static void main(String[] args) {
        SimpleApp s = new SimpleApp();
        s.method(); // interesting?!
    }

    private void method() {
        System.out.println("This is private method!");
    }
}

运行时,在控制台中会显示消息 我想这是因为compilator(或 PHP 解释器)的实现方式。

在这种情况下,您位于SimpleApp类中,因此您可以调用其私有方法(即使在不同的对象上 - 来自外部)。 C#可能有所不同。