0

我正在阅读一些 PHP 代码,我注意到一个类在其兄弟(从一个共同的父级继承)上调用了一个受保护的方法。这让我觉得违反直觉。

in the same inheritance tree在 PHP 中是否意味着类似于 Java 的part of the same package东西?

我更习惯protected.

因为我更习惯 C# 中受保护的含义,所以我没想到能够在同级类上调用受保护的方法。在 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 之前的情况。 这个 RFC 对这个问题进行了更多解释,并指出了为什么这个 bug 发生了变化

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

感谢 Robin F. 为我提供了有关 RFC 的讨论的一些背景信息。

4

3 回答 3

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()(作为类$c1的实例C1),所以输出完全没问题。
你第二次调用$c2->f()所以没有兄弟函数而是C2类函数,这是完全合法的,因为你也覆盖了它。

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

于 2013-10-21T14:16:41.793 回答
0

看起来预期的行为是 PHP 5.2 之前的情况。 这个 RFC 对这个问题进行了更多解释,并指出了为什么这个 bug 发生了变化

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

感谢 Robin F. 为我提供了有关 RFC 的讨论的一些背景信息。

于 2017-07-13T12:27:32.347 回答
-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!");
    }
}

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

在这种情况下,您在 SimpleApp 类中,因此您可以调用它的私有方法(甚至在不同的对象上 - 从外部)。对于C#可能会有所不同。

于 2013-10-21T15:15:30.387 回答