为什么在扩展受保护的 class 变量并将其标记为私有后得到 "Access Level must be protected or weaker"?

Why do I get an "Access Level must be protected or weaker" after extending a protected class variable and marking it private?

abstract class AbstractController
{
    protected $repository;
}

class GraphController extends AbstractController
{
    private $repository;
}

我收到这个错误:

Fatal error: Access level to GraphController::$repository must be protected or weaker

为什么?这背后的理论是什么?在某种程度上,当我扩展 class 时,我对 class 属性(即 public)的访问级别可能较弱,这感觉不对,因为我在某种程度上暴露父 class 意味着更受限制的变量...

这是传承的规则。您可以使继承成员的可见性更弱(更可见),但不能将其隐藏得更多。所以你可以让它受到保护,或者 public。理由是你不应该能够从基础 class 中隐藏成员,或者使成员比基础 class 作者预期的更不可见。添加到,是,从中删除,否。

这是对上面关于使成员变量更可见的评论的回应...不一定是对原始问题的回应。

试试 运行 这个片段。你会看到仍然会有一个私有变量潜伏在你的 public var 下同名,这取决于你是通过 base-class 方法还是 derived-class 方法访问它,你会得到不同的结果,因为它们是两个不同的实例值。

class baseclass {
    private $hideme;
    public function getit() { return $this->hideme; }
    public function setit($value) { $this->hideme = $value; }
}

class derived extends baseclass {
    public $hideme;
}

function doobee(baseclass $obj) {
    echo $obj->getit() . "\n";
}

$a = new derived();
$a->hideme = "direct assign";
$a->setit("accessor assign");

?><pre><?php
echo '$a->getit(); // ' . $a->getit() . "\n";
echo '$a->hideme; // ' . $a->hideme . "\n";
echo 'doobee($a); // '; doobee($a);

echo 'print_r($a);' . "\n";
print_r($a);
?></pre>

输出:

$a->getit(); // accessor assign
$a->hideme; // direct assign
doobee($a); // accessor assign
print_r($a);
derived Object
(
    [hideme] => direct assign
    [hideme:baseclass:private] => accessor assign
)

不只是 PHP 有这种行为;例如 C# 也是如此。

所以我想从这一切中得出的结论是,尝试更改派生 classes 中基 class instance/members 变量的可见性并不是一个好主意。