PHP5 成员可见性


PHP5 member visibility

有人可以解释一下,为什么可以在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可见性(。

它不起作用的原因是,正如您所指定的,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);

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

这两种方法都有优点和缺点...

这在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 (

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

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

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

如果你这样做了,它就行不通了:

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

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