0

有人可以解释一下,为什么可以在 PHP 中执行以下操作,但是,例如,不能在 C# 或 Java 中执行以下操作:

Class A {
    protected $a = 'Howdy!';
}

Class B extends A {
    public function howdy() {
        $created = new A();
        echo $created->a; <----- This is legal due to per-class visibility
    }
}

$b = new B();
echo $b->howdy();  <----- Hence, no fatal error here

此处似乎指定了此行为我无法理解其背后的根本原因 (在我看来,不能简单地实现per-class可见性而不是per-instance没有充分理由的可见性)。

4

5 回答 5

2

这在 C#(和 Java 中)也是可能的。

class A                               // declare new class type B
{
   protected string a = "Howdy!";     // that has a protected member called `a`
}

class B : A                           // declare new type B which extends type A
{
   public void howdy()
   {
       A created = new A();
       Console.WriteLine(created.a);  // no problem accessing a b/c B extends A
   }
}


B bInst = new B();                    // create a new instance of type B
bInst.howdy();                        // invoke it's public method howdy()

基本上发生了什么是这样的:

  • 类 A 包含一个名为的受保护成员a,这意味着它在扩展 A 的类的范围内是可见的(在我们的例子中是类 B)
  • B 类扩展 a 以便它可以访问它的受保护成员(在我们的例子中a
于 2012-05-18T14:01:30.800 回答
2

也可以在 C# 和 Java 中进行。protected表示该变量可以从 A 的任何子类访问。B 是 A 的子类,因此它可以访问该变量。这里没有魔法。

于 2012-05-18T14:02:02.690 回答
2

您链接到的页面有一个标题为“其他对象的可见性”的部分,其中指出:

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

于 2012-05-18T14:07:06.053 回答
2

它不起作用的原因是,正如您所指定的,PHP 在类级别实现访问控制,而其他语言使用实例级别的方法。

为什么有用?它允许您的类在不暴露其私有数据的情况下对其自身的其他实例进行操作。让我们举一个简单的值对象示例:

class Int {
    protected $value = 0;
    public function __construct($value) {
        $this->value = (int) $value;
    }
    public function add(Int $new) {
        return new Int($new->value + $this->value);
    }
}

$a = new Int(1);
$b = new Int(2);
$c = $a->add($b);

这使您可以封装受保护的信息,但仍然可以跨实例使用它......

这两种方法各有利弊...

于 2012-05-18T19:33:41.120 回答
0

如果你这样做是行不通的:

$b = new B();
echo $b->a;

在您的示例中,您没有直接从 B() 访问 $a 成员。您正在从恰好从 B() 内部实例化的 A() 对象访问它。

于 2012-05-18T14:27:57.017 回答