标记界面与空抽象类

时间:2018-04-23 09:11:01

标签: java abstract-class software-design marker-interfaces

我在使用marker interface或空抽象类时遇到困难。

我有两个类BrokerResponseNotification,它们没有结构相似性。连接它们的唯一方法就是需要订阅。

void register(Receivable receivable, BrokerObserver observer)

我不赞成使用Marker Interface,因为它违反了Interface的基本定义。另一方面,使用abstract super课程会让我感到不舒服,因为这两个课程彼此之间没有任何关系。

这种情况下通常更可取的方法是什么?为什么?

编辑1

我忘了提一下,BrokerResponse本身就是一个抽象类,它有几个子类来确定各自的类型。

3 个答案:

答案 0 :(得分:6)

抽象类与标记界面:

标记界面没有任何问题,并且有一些用例。选择这两者之间,标记界面具有更大的灵活性。

如果您确实想要定义类型,请使用界面。

抽象类的目的是提供一个适当的超类,其他类可以从中继承并共享一个共同的设计 - 你的类没有共同的设计,也没有什么可分享的。此外,如果您将来需要为他们添加一个真正不同的父母,那么您将把它们都粘在一些受限制的设计上并且不会那么灵活。

抽象类的用例列表:

  • 在几个密切相关的类之间共享代码。

  • 扩展抽象类的类有许多常用方法或 字段或需要除公共之外的访问修饰符(例如 保护和私人)。

  • 声明可以定义的非静态或非最终字段 可以访问和修改对象状态的方法 他们属于。

用于界面的用例:

  • 不相关的类会实现您的界面。

  • 指定特定数据类型的行为,无需担心 谁实施其行为。

  • 多重遗产的优势。

所有列出的参数都是用于接口的。由于BrokerResponse本身就是抽象的,并且具有自己的层次结构,因此这些类别的共同点更加强大。

作为替代方案,您可以使用标记注释。我会考虑坚持这两种方法中的一种而不是抽象类。

标记界面与标记注释:

根据Joshua Bloch的' 有效的java ':

  

标记接口比标记注释有两个优点。第一   最重要的是,标记接口定义了一个由其实现的类型   标记类的实例;标记注释没有。该   这种类型的存在允许您在编译时捕获错误   如果你使用了标记注释,那么直到运行时才能捕获。   标记接口相对于标记注释的另一个优点是   它们可以更精确地定位。

什么时候应该使用标记注释?

  

如果标记适用于任何程序,则必须使用注释   除了类和接口之外的元素,仅作为类和   可以使用接口来实现或扩展接口。

什么时候应该使用标记界面?

  

问自己这个问题,我想写一个或多个方法   只接受具有此标记的对象?如果是这样,你应该使用   标记接口优先于注释。这将使其成为可能   您可以使用该接口作为方法的参数类型   问题,这将产生编译时的真正好处   类型检查。

要点:

  

如果要定义没有任何新方法的类型   与之相关联的标记界面是最佳选择。

     

如果要标记除类和之外的程序元素   接口,以允许添加更多信息   将来的标记,或者将标记放入框架中   已经大量使用注释类型,然后是标记注释   是正确的选择。

答案 1 :(得分:2)

在这种情况下使用空抽象类没有任何意义,因为Java中没有多重继承。 使您的类实现一些标记接口不会改变您的类层次结构,它只是用一些额外的元数据标记您的类。

如果已经标记为Subscribable的类也应该是例如Writable,则会出现这种情况。如果使用空的抽象类,则需要重新设计整个层次结构。使用marker接口,只需将Writable添加到实现列表即可。

答案 2 :(得分:1)

注释它们怎么样?你得到的答案是,如果你必须选择,使用标记界面是这里的方法,但根据你可能需要做的事情使用注释会更清晰。

事实上,你说你需要让它们以某种方式“相同”来讨论instanceof电话并根据它做一些事情。同样的事情可以通过isAnnotationPresent等来实现。

但是如果你添加一个标记界面,如何使它一个标记界面 - 只是你需要测试有限数量的类?类似MyInterface {boolean isSubscribable();}

的内容