接口作为标签在java OO中是一种不好的做法吗?

Win*_*hen 8 java label interface

在解析某些xml文件的过程中,我遇到了一种情况,我必须使用接口作为标签来识别某些标签属于某个类别,例如,我创建了一个Tag接口来识别这些类用于表示xml标签和ContainableTag指出某些标签可以是某些标签的子标签之一.

然后我偶然发现了这个页面:http://xahlee.org/java-a-day/interface.html(请查看" Interface as Labels "会话.).它说:

问题的关键在于它在语言中是一种数学上无关紧要的东西.作为语言中的标记机制,为了从软件工程角度可能获益,它不应该被设计为类接口的一部分,因为标记的概念和编程接口的概念在语义上是不同的.

那么界面作为标签必然是一种不好的做法?作为一名java程序员,我们还有其他选择吗?

Jhe*_*ico 8

作为标记的接口在很大程度上已被Java 5或更高版本中的注释机制所取代.它们允许您添加任意元数据.如果您的接口是空的并且仅用作类标记,那么您应该使用注释.

  • http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html使用注释的最大问题是,如果你想要保留"运行时",你需要注释你的注释在运行时使用它们.默认情况下,它们会被编译器丢弃. (3认同)
  • 另一个带注释的问题是它们不是默认由子类继承的.您需要在注释上指定@Inherited(http://www.j2ee.me/j2se/1.5.0/docs/api/java/lang/annotation/Inherited.html)以实现该目的 (2认同)

Shi*_*iSi 7

虽然注释可以提供的接口完成的标志替代,他们只是在Java中可用,并且不与IDE很好地集成:我也用标志接口在我的项目标记相关的概念,然后我可以使用类型层次浏览器找到所有成员(我想最终将由主要的IDE支持注释).

至于你提到的那篇文章,我认为如果一个类在语法上/结构上"完成"一个接口,那个接口可能/应该自动应用到类中("Any类可以将它声明为[RandomAccess]为界面......").在我看来,那是倒退的想法.

我认为,其中这样的标记接口中使用的地方,一个'的instanceof"语句,使用倒置的逻辑,但只要你坚持一种语言中没有多重继承,方面和注释,我看不出有什么更好的方法完成这没有走出基本语言.

另请注意,关于始终适用的空接口的这种无关紧要的参数也可以应用于注释.


gus*_*afc 5

注释不一定是您想要的.标记接口是一种将类型属性处理为类型本身的方法.例如,如果您即将开始编写如下代码:

@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
}
Run Code Online (Sandbox Code Playgroud)

然后考虑一下你是否真的不认为这看起来更好:

interface ContainableTag {}

public class Foo implements ContainableTag {}

// ... elsewhere...

public void addElement(ContainableTag ct){
    // add the containable tag as an element
}
Run Code Online (Sandbox Code Playgroud)

当然,标记接口不提供有关类型本身提供的行为的任何信息,但它确实允许其他类型强制执行此非行为属性.如果ObjectOutputStreamwriteObject(Serializable)方法而不是,我当然会幸免于很多烦人的错误writeObject(Object).

编辑:我在这里没有微不足道的支持.