In some cases, it may make sense to define a marker interface which specifically undoes the effect of another marker interface. In general, this should only be done in cases where the purpose of the original marker interface is to indicate a potential optimization, and where the marker's documentation has from the beginning always described its antithesis. In other words, everything that can be done with the base class can be done with the child class (though not necessarily as fast), and no properly-written code will expect the optimization to work on something where it can't.
With regard to things like serialization and cloning, there are three categories of class:
- Those which don't know of any reason why they can't be serialized (or cloned), but don't make a public promise about that, and thus don't make any promises about descendant classes. Descendants may be of types 1, 2, or 3.
- Those which can't be serialized, and whose descendants can't be either. Descendants should all be of type 2.
- Those which publicly promise that they be serialized, with the implication that only classes that can be serialized should derive from them. Descendants should all be of type 3.
If one recognizes that classes may fall into any of the three categories above, a simple pattern for marker interfaces becomes clear. Classes with no serialization-marker interface are of type 1. Those with a "CannotSerialize" marker are type two. Those with a "CanSerialize" are type three. No class should implement both markers.
Unfortunately, I'm not aware of any parts of the Java or .net frameworks which implement that pattern; both seem to assume there are only two types of classes (things that can do something, and those that can't). Still, it's a good pattern for new types moving forward.