在Java面向对象编程中使用接口作为标签是一种不好的做法吗?

10
在解析某些xml文件时,我遇到了这样一种情况:我必须使用接口作为标签来识别某些标记属于某些类别,例如,我创建了一个Tag接口来标识这些类用于表示xml标记,以及ContainableTag来指出某些标记可以成为某些标记的子标记之一。
然后我遇到了这个页面:http://xahlee.org/java-a-day/interface.html(请查找“Interface as Labels”部分)。它说:
引述:

问题的要点是,它在语言中是数学上的无关性。作为语言中的标签机制,出于软件工程的可能好处,它不应该被设计为Class Interface的一部分,因为标签和编程接口的概念在语义上是不同的。

那么,将接口作为标签一定是一种不好的实践吗?作为Java程序员,我们是否有其他选择?

您应该在 Stack Overflow 上指出关于这个主题的现有查询。它们还包含了许多参考资料。不过,你挖掘出来的文章很有趣。 - Volker Stolz
3个回答

9

在Java 5或更高版本中,注释机制已经大量取代了接口作为标记的作用。它们允许您添加任意元数据。如果您的接口为空且仅用作类标记,则应改用注释。


我从来没有深入研究过注解的用法,尽管我在某些框架中使用它。谢谢。我会去谷歌搜索教程。如果您手头有一些注解教程的链接,能否也给我提供一下? - Winston Chen
3
在使用注释时最容易出现的问题是,如果想在运行时使用它们,就需要用 "runtime" 保留策略来为你的注释添加注释。默认情况下,编译器会将它们丢弃。 - Jherico
2
注释的另一个陷阱是,它们默认情况下不会被子类继承。您需要在注释上指定@Inherited (http://www.j2ee.me/j2se/1.5.0/docs/api/java/lang/annotation/Inherited.html) 来实现继承。 - Gregory Mostizky

8
尽管注释可能为标记接口所完成的工作提供了替代方案,但它们仅适用于Java,并且与IDE集成不良:我也使用标记接口在项目中标记相关概念,然后可以使用类型层次结构浏览器查找所有成员(我猜这将很快被主要IDE支持注释)。
至于你提到的文章,我认为争论一个类在语法/结构上“满足”一个接口是否应该自动应用于该类(“任何类都可以将其[RandomAccess]声明为接口...”)毫无意义。在我看来,这是倒退的思路。
我会认为在“instanceof”语句中使用这种标记接口的地方使用了倒置逻辑,但只要你被困在没有多重继承、方面和注释的语言中,我认为没有更好的方法来完成这项工作,除非跳出基础语言。
此外,请注意,关于空接口始终适用的这个无效的争论也可以应用于注释。

6

注释并不一定是你想要的。标记接口是将类型的属性嵌入到类型本身的一种方式。例如,如果你即将开始编写类似于以下代码的代码:

@interface ContainableTag{}

@ContainableTag public class Foo {}

// ... elsewhere...

/**
 * Adds obj as a child element.
 * @throws IllegalArgumentException if obj is not tagged with 
 *         the ContainableTag annotation.
 */
public void addElement(Object obj){
    if (!obj.getClass().isAnnotationPresent(ContainableTag.class))
        throw new IllegalArgumentException("obj is not a ContainableTag");
    // add the containable tag as an element
}

那么请考虑一下,您是否真的认为这样看起来不太好:
interface ContainableTag {}

public class Foo implements ContainableTag {}

// ... elsewhere...

public void addElement(ContainableTag ct){
    // add the containable tag as an element
}

当然,标记界面并不提供有关类型本身提供何种行为的任何信息,但它确实允许其他类型强制执行这种非行为属性。如果ObjectOutputStream具有writeObject(Serializable)方法而不是writeObject(Object),我肯定会避免很多烦人的错误。 编辑:我在这里有相当大的支持

1
哈哈,我的《Effective Java》太老了,没有这篇文章。谢谢。 - Winston Chen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接