有人可以解释一下,为什么可以在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(( 对象访问它。