是否有理由使用private
关键字代替protected
?当有一些在子类中没有意义的缓存属性或辅助方法时,我可以理解它的目的。我在许多重要课程中看到private
,但我没有看到它的目的。这是一个Symfony示例:Symfony's HttpException class:
namespace Symfony\Component\HttpKernel\Exception;
class HttpException extends \RuntimeException implements HttpExceptionInterface
{
private $statusCode;
private $headers;
public function __construct($statusCode, $message = null, \Exception $previous = null, array $headers = array(), $code = 0)
{
$this->statusCode = $statusCode;
$this->headers = $headers;
parent::__construct($message, $code, $previous);
}
public function getStatusCode()
{
return $this->statusCode;
}
public function getHeaders()
{
return $this->headers;
}
}
有没有理由说这些不是protected
?我唯一能想到的就是让程序员自己声明它们的代码可读性,但我对此并不那么肯定。请在此处告诉我您对private
关键字的使用情况。
答案 0 :(得分:1)
是的,绝对有理由,理由是Liskov替代原则或者" L"在" SOLID"如果你愿意的话。
Liskov替换原则指出,如果您的类型T
和类型S
是T
的子类型,那么您应该能够替换{{1}类型的任何对象1}}使用T
类型的对象而不改变程序的正确性。
S
成员是创建违反Liskov替换的常用方法,因为它们允许您覆盖超类型中的行为。
这在理论上是伟大的,但它究竟意味着什么?
继承创建的是关系是类型之间非常强大的连接,远比公共接口或组合强,因为它意味着实现共享。 Liskov替换违规的典型示例是Circle-Ellipse问题,请参阅:https://en.wikipedia.org/wiki/Circle-ellipse_problem
在生产环境中,这种问题更为重要,其他开发人员可能最终依赖于他们认为由超类型存在所保证的行为,但实际上由于LSP违规而无法保证 - 在最糟糕的情况下,他们可能最终依赖于不正确的行为,以至于超级类中的合法错误修复会在其他地方造成问题。
每当你使一个对象/方法比protected
更易于访问时,你实际上会向其他开发人员提供保证,在他们的子类型中,他们可以以几乎任何可想象的方式更改该特定行为,并且您的代码仍然可以正常运行所以每次做出这个决定时,你都要问自己,你做出这种保证的能力有多大。如果你对此没有信心,那么就不要这样做。
确保您不会像通过private
成员那样通过protected
成员泄漏课程的实施细节,这一点同样重要。陷阱可能有点令人讨厌。
这是对象组成通常优于继承的一个原因。原则上遗传没有任何问题,但是类型和超类型之间的关系非常强大,确保只有在适当的情况下才能使用这种关系非常重要。
让我们看一下您的示例,例如,它有一个public
状态代码。目前,该状态代码实际上是不可变的,它在构造函数中设置一次,并且不能被类中任何暴露的方法变异。这很好,因为它是一个例外,我们不希望它改变,我们想知道最初导致它的原因。
如果您要成为private
成员,则不再保证这一点。 protected
的子类型在一个时刻代表一个错误,理论上可以代表下一个完全不同的错误。在那种情况下,班级不再具有任何意义,它没有达到其目的。
答案 1 :(得分:0)
是的,特别是如果你写其他人会使用的课程,这是有充分理由的。通过隐藏实现和限制访问,可以重构类,而不必担心破坏类的任何用户。