【问题标题】:Why does PHP allow protected and private methods to be made public via an override in subclasses?为什么 PHP 允许通过子类中的覆盖将受保护和私有方法公开?
【发布时间】:2012-03-11 18:35:02
【问题描述】:

通过一些简短的摆弄,我发现在执行以下操作时在子类中覆盖超类方法时出现错误:

  • 用私有子类方法覆盖受保护的超类方法
  • 用受保护或私有子类方法覆盖公共超类方法

但是,如果我在另一个方向这样做,则不会引发错误:

  • 用受保护或公共子类方法覆盖私有超类方法
  • 用公共子类方法覆盖受保护的超类方法

这对我来说似乎违反直觉 - 我期待它以相反的方式工作以强制执行信息隐藏和封装。通过允许以可能破坏其他方法的方式暴露内部结构,这似乎允许糟糕的设计,我看不出这是一个好主意的情况。为什么以这种方式实施,我错过了什么?

另外,这是其他编程语言的标准做法吗?

【问题讨论】:

  • 我的意思是,为了防止组件之间产生依赖关系,最好坚持只公开最少数量的公共方法。允许公开私有方法会鼓励其他开发人员使用它们,因此会破坏使用多态性交换类的能力。
  • 如果我错了,请纠正我:编程语言是一种工具,应该尽可能灵活;代码、模式和行为的设计取决于开发人员的良心。现在,如果我们假设您不是在谈论外部漏洞,那么您真的是在谈论来自一个团队的程序员破坏开发吗?
  • 好吧,为了尽可能灵活,它根本不会有公共/私有/保护 :) 我真正要问的是“为什么有时有必要公开私人事物”,因为我无法设想有帮助的用例。另一方面,我确信有时必须有一个,否则它会抛出一个错误,以便根据包含公共/私有/受保护的决定来帮助实施良好的设计。或者我假设。
  • 您不能公开私有方法。它们将是两个不同的方法。
  • 基本上,您可以添加到子类中,但不能从中删除。

标签: php oop inheritance visibility encapsulation


【解决方案1】:

您所说的“强制信息隐藏”是一种可能会破坏子类的东西,因为属性和方法可能会突然消失。你不能通过这种方式放松限制来破坏事情。

private 有点不同:在这种情况下,从子类的角度来看,属性/方法不存在。因此,没有理由为什么子类不能引入具有该名称的属性,因为它将是一个 不同 属性。

您是对的,这可能会导致设计不佳,但您始终可以构建设计不佳的应用程序。

【讨论】:

  • 嗯我同意马特。这根本不符合逻辑。对我来说,应该只有一种脚本方式:每个子类都必须尊重超类(在各个方向)的属性的可见性。
  • @iRaS 您缺少的是私有属性/方法根本不是关于“信息隐藏”,而是关于防止行为被子类覆盖或影响。如果您在子类中创建一个新的私有/公共方法,该方法与父类中的私有方法同名,则父类不会调用该方法(除非它使用后期静态绑定来调用它)
【解决方案2】:

你不能降低班级成员的知名度,只能提高他们的知名度。

想象一个类 A 有一个公共方法,而一个子类 B 会将其设为私有。 B 可以被视为 A 类型,假设它具有该公共方法。

【讨论】:

  • 是的,我明白你的意思,但如果你这样做,肯定会出现类似的问题:你的代码变得依赖于 B 已公开的函数,而 A 仍将其声明为私有?我想我认为公共和私有/受保护不应通过继承互换。
  • 它确实可能会破坏封装。我个人不经常这样做,如果有的话。但它仍然不会影响 A,因为 A 应该被视为 A,而不是 B。这确实不是我想说的最好的设计。
【解决方案3】:

如果一个超类公开了一个方法,那么它的所有子类也必须公开相同的方法(或覆盖的版本),因此在 PHP 中降低方法的可访问性是一个子类是非法的(几乎所有基于类的OO 语言)。

反之则不然,因此增加子类中方法的可访问性是非常好的。

【讨论】:

    【解决方案4】:

    如果您认为在子类中公开私有/受保护方法存在问题,只需将方法设为 final。

    这样看:NOT 将方法设为final,您就允许任何子类随意覆盖它;这显然包括提高其知名度。

    【讨论】:

      猜你喜欢
      • 2014-11-03
      • 2019-02-13
      • 2016-12-26
      • 2017-09-14
      • 2012-04-10
      • 2015-10-01
      • 1970-01-01
      相关资源
      最近更新 更多