【问题标题】:Why aren't classes sealed by default?为什么默认情况下不密封类?
【发布时间】:2008-10-31 00:38:58
【问题描述】:

我只是想知道,既然 sealed 关键字的存在表明,是否允许其他类继承它是类作者的决定,为什么默认情况下类不密封,有一些关键字将它们显式标记为可扩展?

我知道这有些不同,但访问修饰符以这种方式工作。默认设置是限制性的,只有插入关键字才能授予更全面的访问权限。

不过,我很有可能没有正确考虑到这一点,所以请保持人道!

【问题讨论】:

  • 我认为,如果您将类默认密封,那么这意味着您不应该使用面向对象的语言。
  • 我在 .NET Framework 中遇到了太多次我想要继承和覆盖功能的密封类。内部也是如此。
  • 一种有对象和消息但没有继承的语言不是面向对象的,而仅仅是基于对象的
  • @Chris:如果您仍然对密封的 .NET Framework 类不满意,您可能会发现 blogs.msdn.com/b/ericlippert/archive/2004/01/22/61803.aspx 是一本有趣的书。
  • 来自 MSDN:要确定是否密封类、方法或属性,通常应考虑以下两点:1) 派生类可能通过自定义类的能力获得的潜在好处. 2)派生类可能会修改您的类,使其不再正常工作或按预期工作。 . .我的偏好是,如果我作为一个类的作者不需要额外的工作来允许其他人从中派生,我不会将它标记为密封。但是,如果我的课程不是为以某种微妙的方式派生而设计的,请密封它。

标签: c# inheritance sealed


【解决方案1】:

我会说这只是一个错误。我认识很多人(包括我自己)认为课程确实应该默认密封。那个阵营的 C# 设计团队中至少有几个人。自从 C# 最初设计以来,钟摆已经在某种程度上偏离了继承。 (当然,它有它的位置,但我发现自己很少使用它。)

对于它的价值,这并不是与 Java 过于接近的唯一错误:我个人宁愿 Equals 和 GetHashCode 不在对象中,并且您也需要特定的 Monitor 实例来锁定......

【讨论】:

  • C# 团队中谁是亲密封级的?
  • Eric Lippert,我也相信 Cyrus。 (不过我不认为他们中的任何一个都在 v1 的团队中。)
  • 如果 GetHashCode 不在对象中,那么每个聚合器(甚至不是继承者)都必须有权访问每种类型的私有数据,并且聚合器必须为每种类型滚动自己的哈希。你真的认为这会减轻编程的痛苦吗?
  • @Windows:这些都不是。你可以可选地在有意义的地方实现相等和GetHashCode,实现一个接口。可以包括一个系统 IEqualityComparer 来进行身份比较。其他比较可以基于公共财产。会好的。
  • C#的三大错误:default mutable、default unsealed、default nullable。
【解决方案2】:

在我看来不应该有默认语法,这样你总是可以明确地写出你想要的。这迫使编码人员理解/思考更多。

如果你想让一个类是可继承的,那么你写

public extensible class MyClass

否则

public sealed class MyClass

顺便说一句,我认为访问修饰符也应该如此,不允许默认访问修饰符。

【讨论】:

  • 好点子,您必须始终清楚自己在做什么,而不是有意或无意地退回到不可见的默认值。
  • 你可以考虑使用抽象修饰符来实现继承
  • 如果没有提供关键字会怎样?只需public class MyClass
  • 我明白你的意思——尽管事情可能会变得非常冗长。明智地,为开发人员做出明智的默认、常规决策似乎是事情的发展方向......
【解决方案3】:

继承是 OO 的基本原则,因此可以说,默认情况下不允许它是不直观的。

【讨论】:

  • 我认为很多人会争辩说,大多数类不是旨在继承自。
  • 我还认为大多数开发人员在构建类时并没有考虑到继承。
  • Mike 和 Steve,如果您遵循良好的 OO 实践,那么您将设计可继承和重用的类。
  • @Chris:不可能。大多数类永远不会派生,猜测哪些元素需要专门化不仅浪费时间,而且会限制未来实现决策的过程。请参阅 Effective Java 以获得对此的详细讨论。
  • 如果我可以投票赞成评论,我会为 Jon 的评论投票 - 这是基本点 - 为继承设计确实需要大量的深思熟虑,并且绝大多数时间是不需要的 - 所以为什么要默认使用需要开发人员浪费脑力周期的东西??
【解决方案4】:

您可能会提出尽可能多的论据来支持默认密封,因为您可以反对它。如果反过来,就会有人发布相反的问题。

【讨论】:

    【解决方案5】:

    我不记得听说过默认情况下不密封类的决定的理由。但是,肯定有不少人认为 C# 应该被指定为默认密封:

    http://codebetter.com/blogs/patricksmacchia/archive/2008/01/05/rambling-on-the-sealed-keyword.aspx

    【讨论】:

      【解决方案6】:

      密封类防止继承,因此是一种面向对象的可恶。详情见this rant ;-)

      【讨论】:

      • 感谢不加评论的路过投票 - 懦夫! :-P
      • 就个人而言,我认为实现继承的重要性被夸大了。而且,我通常同意默认值应该被密封的说法——继承非常容易搞砸。在可行的情况下,通常应该使用组合来代替。所以,我非常不同意你的观点 :) 对我来说,OO 开发的主要优势是接口和多态性。
      • @[Phil]:那么,每次创建windows窗体时,是否封装了一个Form对象而不是继承自System.Windows.Form?似乎需要做很多额外的工作......继承是基础;学习它,生活它,爱它;-)
      • @StevenA.Lowe 为了繁荣,我应该指出Form 旨在扩展,这就是这场辩论的重点。在你和我看来,设计可扩展代码的人应该茁壮成长,但经验证据表明,遗憾的是太多人不这样做。因此,是否密封类没有理论上的区别;这些类不能扩展,因为它们不是为它设计的,期间。唯一实际的区别是,在一种情况下它是显而易见的(密封的),而在另一种情况下,当它在运行时崩溃时你会发现它。
      【解决方案7】:

      Word 80% 的功能未被使用。 80% 的类不会被继承。在这两种情况下,偶尔会有人出现并想要使用或重用某个功能。为什么原设计者要禁止重复使用?让重用者决定他们想要重用什么。

      【讨论】:

      • 这是一个反对密封关键字存在的论据,而不是默认的:)
      【解决方案8】:

      仅从未密封的类派生不会改变该类的行为。可能发生的最坏情况是基类的新版本将添加一个与派生类同名的成员(在这种情况下,只会出现编译器警告说您应该使用 newoverride 修饰符)或基类是密封的(如果该类已经被释放到野外,这是一个设计禁忌)。任意子类化仍然符合Liskov Substitution Principle

      在 C# 中默认情况下成员不可重写的原因是因为重写方法可以以基类作者未预料到的方式改变基类的行为。通过使其明确抽象或虚拟,意味着作者意识到它可以改变或超出他们的控制范围,作者应该考虑到这一点。

      【讨论】:

        【解决方案9】:

        出于同样的原因,默认情况下对象不是私有的

        与对象类比一致,即对象默认不是私有的

        只是猜测,因为归根结底这是一种语言的设计决定,而创作者所说的是经典材料。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-07-07
          • 2019-09-24
          • 2012-04-25
          • 1970-01-01
          • 1970-01-01
          • 2021-11-21
          相关资源
          最近更新 更多