你什么时候、为什么要封闭一个班级?

发布于 2024-12-10 05:16:04 字数 196 浏览 0 评论 0原文

在 C# 和 C++/CLI 中,关键字 sealed(或 VB 中的 NotInheritable)用于保护类免受任何继承机会(该类将是不可继承的)。我知道面向对象编程的一个特性是继承,我觉得使用 sealed 违背了这一特性,它会停止继承。 是否有一个示例展示了密封的好处以及何时使用它很重要?

In C# and C++/CLI the keyword sealed (or NotInheritable in VB) is used to protect a class from any inheritance chance (the class will be non-inheritable). I know that one feature of object-oriented programming is inheritance and I feel that the use of sealed goes against this feature, it stops inheritance.
Is there an example that shows the benefit of sealed and when it is important to use it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

忆沫 2024-12-17 05:16:04
  1. 在实现安全功能的类上,使得原始对象无法被“模拟”。

  2. 更一般地说,我最近与微软的一个人交流,他告诉我他们试图将继承限制在真正有意义的地方,因为如果不加以处理,它会在性能方面变得昂贵。
    关键字告诉 CLR 没有类可以进一步查找方法,这样可以加快速度。

在当今市场上的大多数性能增强工具中,您会发现一个复选框,它将密封所有未继承的类。
但要小心,因为如果您想允许通过 MEF 发现插件或程序集,您将会遇到问题。

  1. On a class that implements security features, so that the original object cannot be "impersonated".

  2. More generally, I recently exchanged with a person at Microsoft, who told me they tried to limit the inheritance to the places where it really made full sense, because it becomes expensive performance-wise if left untreated.
    The sealed keyword tells the CLR that there is no class further down to look for methods, and that speeds things up.

In most performance-enhancing tools on the market nowadays, you will find a checkbox that will seal all your classes that aren't inherited.
Be careful though, because if you want to allow plugins or assembly discovery through MEF, you will run into problems.

谜泪 2024-12-17 05:16:04

Louis Kottmann 的出色答案的附录:

  1. 如果一个类不是为继承而设计的,则子类可能会破坏类不变量。当然,这只适用于您创建公共 API 的情况,但根据我的经验,我会密封任何未明确设计为子类化的类。

相关说明,仅适用于未密封的类:创建虚拟的任何方法都是扩展点,或者至少看起来应该是扩展点。声明方法虚拟也应该是一个有意识的决定。 (在 C# 中,这是一个有意识的决定;在 Java 中则不然。)

然后就是:

  1. 密封会使单元测试变得更加困难,因为它禁止模拟。

一些相关链接:

另请注意Kotlin 默认情况下密封类; open 关键字与 Java 的 final 相反 或 C# 的 sealed。 (可以肯定的是,没有人普遍认为这是一件好事< /a>。)

An addendum to Louis Kottmann's excellent answer:

  1. If a class isn't designed for inheritance, subclasses might break class invariants. This really only applies if you're creating a public API, of course, but as I rule of thumb I seal any class not explicitly designed to be subclassed.

On a related note, applicable to unsealed classes only: any method created virtual is an extension point, or at least looks like it should be an extension point. Declaring methods virtual should be a conscious decision as well. (In C# this is a conscious decision; in Java it isn't.)

And then there's this:

  1. Sealing can make unit testing more difficult, as it prohibits mocking.

Some relevant links:

Also note that Kotlin seals classes by default; its open keyword is the opposite of Java's final or the sealed of C#. (To be sure, there is no universal agreement that this is a good thing.)

我不吻晚风 2024-12-17 05:16:04

将类标记为Sealed 可防止对可能危及安全性或影响性能的重要类进行篡改。

很多时候,当我们设计一个具有固定行为的实用程序类(我们不想改变它)时,密封一个类也是有意义的。

例如,C#中的System命名空间提供了许多密封的类,例如String。如果不密封,则可以扩展其功能,这可能是不可取的,因为它是具有给定功能的基本类型。

同样,C# 中的结构始终是隐式密封的。因此,不能从另一种结构派生一种结构/类。这样做的原因是,结构仅用于建模独立、原子、用户定义数据类型,我们不想修改这些数据类型。

有时,当您构建类层次结构时,您可能希望根据域模型或业务规则限制继承链中的某个分支。

例如,ManagerPartTimeEmployee 都是 Employee,但您在组织中除了兼职员工之外没有任何角色。在这种情况下,您可能需要密封 PartTimeEmployee 以防止进一步分支。另一方面,如果您有每小时或每周兼职员工,则从 PartTimeEmployee 继承它们可能是有意义的。

Marking a class as Sealed prevents tampering of important classes that can compromise security, or affect performance.

Many times, sealing a class also makes sense when one is designing a utility class with fixed behaviour, which we don't want to change.

For example, System namespace in C# provides many classes which are sealed, such as String. If not sealed, it would be possible to extend its functionality, which might be undesirable, as it's a fundamental type with given functionality.

Similarly, structures in C# are always implicitly sealed. Hence one cannot derive one structure/class from another structure. The reasoning for this is that structures are used to model only stand-alone, atomic, user-defined data types, which we don't want to modify.

Sometimes, when you are building class hierarchies, you might want to cap off a certain branch in the inheritance chain, based on your domain model or business rules.

For example, a Manager and PartTimeEmployee are both Employees, but you don't have any role after part-time employees in your organization. In this case, you might want to seal PartTimeEmployee to prevent further branching. On the other hand, if you have hourly or weekly part-time employees, it might make sense to inherit them from PartTimeEmployee.

若言繁花未落 2024-12-17 05:16:04

我认为这篇文章有一些好处,具体情况是当尝试将非密封类转换为任何随机接口时,编译器不会抛出错误;但是当使用 seal 时,编译器会抛出无法转换的错误。密封类带来了额外的代码访问安全性。
https:// www.codeproject.com/Articles/239939/Csharp-Tweaks-Why-to-use-the-sealed-keyword-on-cla

I think this post has some good point, the specific case was when trying to cast a non-sealed class to any random interface, compiler doesn't throw error; but when sealed is used the compiler throws error that it can't convert. Sealed class brings additional code access security.
https://www.codeproject.com/Articles/239939/Csharp-Tweaks-Why-to-use-the-sealed-keyword-on-cla

未蓝澄海的烟 2024-12-17 05:16:04

密封是一个有意识的决定,只有当您想清楚地揭示您对类的结构特征的意图时才应该考虑。这是关于对象模型的结构选择。它永远不应该是关于性能或安全性的决定(**)。但更重要的是,永远不要对继承树进行任意限制。

我提出这个经验法则:
如果您必须考虑密封某个类是否是一个好主意,则永远不应该密封该类。密封一个类的决定对您来说应该是显而易见的,甚至在您编写该类的第一行代码之前就会做出。

举个例子,因为我们无法从它们派生,但它们看起来非常像常规的类中,我们经常将结构体视为密封类。这就是他们的本质。正是这种限制使它们能够实现值类型语义,因为继承和多态性只能与引用类型一起使用。因此“结构类”是密封的,因为任何实现值类型语义的类都必须放弃继承并以不同的方式管理其内存。 (请注意,这对于 C# 中的任何值类型对象都是如此,而不仅仅是结构)。

另一个例子:代码生成器可以编写一个代表窗口及其所有元素的密封类,供用户定义行为,因为 UI 引擎需要这个类,而不是其他类,以便能够呈现窗口。

最后一个例子:数学实用程序类可能是密封的,因为它是围绕不言而喻构建的,并且任何扩展行为永远不可能是正确的或“按预期工作”。这是一个并不完全属于上述经验法则的例子。永远不要盲目相信经验法则。


(**) 如果性能是您的应用程序中的一个问题,您可以确定未密封的类不是原因。同样,如果您依赖密封类来增强应用程序的安全性,那么问题一定出在您的基类上——它们公开或允许扩展的内容。

Sealing is a conscious decision that should be considered only when you want to clearly reveal your intent about the structural characteristics of your class. It is a structural choice about your object model. It should never be a decision about performance, or security(**). But more importantly, never about arbitrary limits to your inheritance tree.

I am putting forward this rule of thumb:
A class should never be sealed if you have to think whether it is a good idea to seal it. A decision to seal a class should be obvious to you and will be made even before you write the class's first line of code.

As an example, since we can't derive from them but they look so much like a regular class, we often think of structs as sealed classes. Which is what they are. It is this limitation that allows them to implement value-type semantics since inheritance and polymorphism can only work with reference types. So the "struct class" is sealed because any class that implements value-type semantics must give away inheritance and have its memory managed differently. (Note that this is true of any value-type object in C#, not just structs).

Another example: A code generator may write a sealed class representing a window and all its elements for the user to define the behavior on, because the UI engine expects this class, and no other, in order to be able to render the window.

And last example: A math utility class may be sealed because it is built around truisms, and any extended behavior can never be correct or "work as intended". This is one example that doesn't exactly fall under the rule of thumb above. Never blindly trust rules of thumb.


(**) If performance is an issue in your application, you can be sure unsealed classes are not the reason. Similarly, if you depend on sealed classes to enforce security in your application, the problem must be on your base classes -- what they expose or allow to be extended.

·深蓝 2024-12-17 05:16:04

如果您的设计模式使用单例,您可能希望密封该类,以便只能创建 1 个实例。基本上,密封该类,创建一个私有构造函数和公共静态方法来返回该类。

If your design pattern is using singletons, you would want to seal the class so that only 1 instance can ever be created. Basically, seal the class, create a private constructor, and public static method to return the class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文