views:

206

answers:

3

During the parsing of certain xml files, I come across a situation that I have to use interface as labels to identify that certain tags belong to certain category, for example, I created a Tag interface to identify that these classes are used to represent xml tags, and ContainableTag to point out that certain tags can be one of the children tags of some tags.

Then I stumble into this page: http://xahlee.org/java-a-day/interface.html (Please look for the "Interface as Labels" session.). It says:

The gist of the problem is that it is a piece of mathematical irrelevance in the language. As a labeling mechanism in a language, for the possible benefit from the software engineering perspective, then it should not be designed as part of the Class Interface, since the concept of labeling, and concept of programing interface, are semantically disparate.

So is interface as labels necessarily a bad practice? As a java programmer, do we have some other alternatives?

+6  A: 

Interfaces as markers have largely been replaces by the annotation mechanism in Java 5 or later. They allow you to add arbitrary meta-data. If your interfaces are empty and are only serving to act as class markers, then you should be using annotations instead.

Jherico
I never look into the usages of annotations, although I use it in certain frameworks. Thank you. I will google for tutorials.Could you also pass me some links of annotation tutorial if you happen to have some at hand?
Winston Chen
http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.htmlThe biggest gotcha in using annotations is that you need to annotate your annotations with a retention of 'runtime' if you want to use them at runtime. By default they're discarded by the compiler.
Jherico
Great! Thank you very much.
Winston Chen
Another gotcha with annotations is that they are not inherited by default by the subclasses. You need to specify @Inherited (http://www.j2ee.me/j2se/1.5.0/docs/api/java/lang/annotation/Inherited.html) on the annotation to achieve that
Gregory Mostizky
+4  A: 

Annotations are not necessarily what you want. Tagging interfaces are a way of working a property of a type into the type itself. For example, if you're about to start writing code looking like this:

@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
}

Then consider if you really don't think this looks better:

interface ContainableTag {}

public class Foo implements ContainableTag {}

// ... elsewhere...

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

Sure, the tagging interface does not provide any information about what behavior the type itself provides, but it does allow other types to enforce this non-behavioral property. I certainly would have been spared a lot of annoying bugs if ObjectOutputStream had a writeObject(Serializable) method rather than writeObject(Object).

Edit: I have not insignificant support here.

gustafc
Haha.. my "effective java" is too old to have this article. Thank you.
Winston Chen
+3  A: 

While annotations may provide an alternative for what marker interfaces accomplish, they are only available in Java, and do not integrate well with IDEs: I also use marker interfaces to tag related concepts in my project, and I can then use the type hierarchy browser to find all members (I guess this will be eventually supported by major IDEs for annotations soon).

As for the article you mention, I do not see the point in arguing that if a class syntactically/structurally "fulfills" an interface, that interface may/should be applied automatically to the class ("Any class can declare it [RandomAccess] as a interface..."). That's backwards thinking, in my opinion.

I would argue that the places, where such a marker interface is used in an `instanceof' statement, use inverted logic, but as long as you are stuck within a language without multiple inheritance, aspects and annotations, I see no better way to accomplish this without stepping out of the base language.

Also note that this dead-beat argument about an empty interface always being applicable could also be applied to annotations.

ShiDoiSi
Nice points. Thanks.
Winston Chen