我经常发现自己想要这样做。当您想要存储一些有用的信息或额外的状态时,它会非常有用。
所以我的问题是,是否有一个非常好的/强有力的理由为什么这是被禁止的?
谢谢
编辑:非常感谢所有这些答案。所以听起来对此没有正确或错误的答案。
假设我接受这些类不是子类的事实,那么不标记Control类的最终结果是什么,但是禁止子类化 - 有效地将异常/错误从编译时降级到运行时?
编辑^ 2:看到我自己的答案:显然,这些类是可重写的,但需要由覆盖者明确确认。
谢谢
在任何答案中看起来都没有人提到这一点,但SWT确实提供了一个可重写的checkSubclass()
方法;确切地说,抛出Unextendable异常的地方。将方法重写为no-op并有效地扩展合法性。我想让这个选项保持打开最终是因为该类没有成为最终的并且扩展错误没有编译时而不是运行时。
例:
@Override
protected void checkSubclass() {
// allow subclass
System.out.println("info : checking menu subclass");
}
为继承设计组件很难,并且可以限制将来的实现更改(当然,如果您保留一些可覆盖的方法,并从其他方法调用它们)。禁止子类化限制用户,但意味着编写健壮的代码更容易。
这遵循Josh Bloch关于“继承设计或禁止设计”的建议。这在开发社区中是一个宗教话题 - 我同意这种观点,但是其他人更喜欢一切尽可能地开放。
创建可以安全子类化的类非常困难。你必须考虑无休止的用例,并保护你的课程。我相信这是将API类标记为final的一般原因。
至于你的后续问题:
什么是不标记Control类final,但禁止子类化 - 有效地将异常/错误从编译时降级到运行时?
如果他们将Control
类标记为final,那么SWT不可能继承它。但他们必须在内部。所以他们将检查推迟到运行时。
顺便说一句,如果你想要一个疯狂的黑客,你仍然可以通过将你的子类放入Control
包中来继承org.eclipse.swt.widgets
或任何其他SWT类。但我从来没有真的那么做过。
org.eclipse.swt.widgets.Widget.checkSubclass()
的方法描述说:
检查此类是否可以是子类。
SWT类库仅在特定的受控点(最值得注意的是,实现新窗口小部件时为Composite和Canvas)进行子类化。除非被覆盖,否则此方法会强制执行此规则。
重要提示:通过提供此方法的实现,该方法允许创建通常不允许创建子类的类的子类,实现者同意完全负责任何此类子类可能在SWT版本之间失败并且将强烈特定平台。没有为以这种方式实现的用户编写的类提供支持。
在允许的SWT类之外进行子类化的能力纯粹是为了使那些不在SWT开发团队中的人能够实现补丁,以便在团队可以解决这些限制之前解决特定限制。如果没有对层次结构的详细和详细的了解,就不应该尝试子类化。
抛出:SWTException ERROR_INVALID_SUBCLASS - 如果此类不是允许的子类