我在使用marker interface或空抽象类时遇到困难。
我有两个类BrokerResponse
和Notification
,它们没有结构相似性。连接它们的唯一方法就是需要订阅。
void register(Receivable receivable, BrokerObserver observer)
我不赞成使用Marker Interface
,因为它违反了Interface
的基本定义。另一方面,使用abstract super
课程会让我感到不舒服,因为这两个课程彼此之间没有任何关系。
这种情况下通常更可取的方法是什么?为什么?
我忘了提一下,BrokerResponse
本身就是一个抽象类,它有几个子类来确定各自的类型。
答案 0 :(得分:6)
抽象类与标记界面:
标记界面没有任何问题,并且有一些用例。选择这两者之间,标记界面具有更大的灵活性。
如果您确实想要定义类型,请使用界面。
抽象类的目的是提供一个适当的超类,其他类可以从中继承并共享一个共同的设计 - 你的类没有共同的设计,也没有什么可分享的。此外,如果您将来需要为他们添加一个真正不同的父母,那么您将把它们都粘在一些受限制的设计上并且不会那么灵活。
抽象类的用例列表:
在几个密切相关的类之间共享代码。
扩展抽象类的类有许多常用方法或 字段或需要除公共之外的访问修饰符(例如 保护和私人)。
声明可以定义的非静态或非最终字段 可以访问和修改对象状态的方法 他们属于。
用于界面的用例:
不相关的类会实现您的界面。
指定特定数据类型的行为,无需担心 谁实施其行为。
多重遗产的优势。
所有列出的参数都是用于接口的。由于BrokerResponse
本身就是抽象的,并且具有自己的层次结构,因此这些类别的共同点更加强大。
作为替代方案,您可以使用标记注释。我会考虑坚持这两种方法中的一种而不是抽象类。
标记界面与标记注释:
根据Joshua Bloch的' 有效的java ':
标记接口比标记注释有两个优点。第一 最重要的是,标记接口定义了一个由其实现的类型 标记类的实例;标记注释没有。该 这种类型的存在允许您在编译时捕获错误 如果你使用了标记注释,那么直到运行时才能捕获。 标记接口相对于标记注释的另一个优点是 它们可以更精确地定位。
什么时候应该使用标记注释?
如果标记适用于任何程序,则必须使用注释 除了类和接口之外的元素,仅作为类和 可以使用接口来实现或扩展接口。
什么时候应该使用标记界面?
问自己这个问题,我想写一个或多个方法 只接受具有此标记的对象?如果是这样,你应该使用 标记接口优先于注释。这将使其成为可能 您可以使用该接口作为方法的参数类型 问题,这将产生编译时的真正好处 类型检查。
要点:
如果要定义没有任何新方法的类型 与之相关联的标记界面是最佳选择。
如果要标记除类和之外的程序元素 接口,以允许添加更多信息 将来的标记,或者将标记放入框架中 已经大量使用注释类型,然后是标记注释 是正确的选择。
答案 1 :(得分:2)
在这种情况下使用空抽象类没有任何意义,因为Java
中没有多重继承。
使您的类实现一些标记接口不会改变您的类层次结构,它只是用一些额外的元数据标记您的类。
如果已经标记为Subscribable
的类也应该是例如Writable
,则会出现这种情况。如果使用空的抽象类,则需要重新设计整个层次结构。使用marker接口,只需将Writable
添加到实现列表即可。
答案 2 :(得分:1)
注释它们怎么样?你得到的答案是,如果你必须选择,使用标记界面是这里的方法,但根据你可能需要做的事情使用注释会更清晰。
事实上,你说你需要让它们以某种方式“相同”来讨论instanceof
电话并根据它做一些事情。同样的事情可以通过isAnnotationPresent
等来实现。
但是如果你添加一个标记界面,如何使它不一个标记界面 - 只是你需要测试有限数量的类?类似MyInterface {boolean isSubscribable();}