tags:

views:

286

answers:

5

If I have a class that needs to implement an interface but one or more of the methods on that interface don't make sense in the context of this particular class, what should I do?

For example, lets say I'm implementing an adapter pattern where I want to create a wrapper class that implements java.util.Map by wrapping some immutable object and exposing it's data as key/value pairs. In this case the methods put and putAll don't make sense as I have no way to modify the underlying object. So the question is what should those methods do?

+16  A: 

Any method that cannot be implemented according to the semantics of the interface should throw an UnsupportedOperationException.

Mike Deck
UnsupportedOperationException is usually the way to go, unless you know that the method will be called anyway, and you want to to do more of a "no-op", in which case returning null or similar is the best you can do.
skaffman
well... it seems you answered your own question there, Mike..
Sandman
The fact you need to do this could be considered a design issue.
Aidos
@Aidos, I agree if I had designed the interface, but there are some 3rd party libraries which have interfaces that are not very cohesive. Sometimes I want to leverage part of an API but other parts of it just don't make sense in the context of my application.
Mike Deck
+9  A: 

That depends on your business case. 2 options:

Use whichever makes more sense. If you do nothing, you are not obeying the contract of the interface. However, throwing a runtime exception can wreak havoc on the calling code. Thus, the decision will have to be made based on how you will be using the class. Another option would be to use a simpler or different interface, if possible.

Do note that the Java library goes the exception route in the specific case of read-only collections.


It was noted below that UnsupportedOperationException is a part of the java collections framework. If your situation is outside of collections, and the semantics bother you, you can roll your own NotImplementedException, or if you are already using commons-lang, you could use theirs.

Chris Marasti-Georg
+3  A: 

Your two choices are really only:

  1. Do nothing.
  2. Throw an exception.

Both have disadvantages. In the first case, by having an empty method, you could mislead the programmer into thinking something happened to your data. The second case breaks the whole idea of polymorphism inherent in interfaces.

David Arno
+2  A: 

Note that UnsupportedOperationException is only OK because of the particular property of the Java Collections Framework, that implementations are permitted to "goof off" implementing part of the interface because they're immutable.

So it's fine for put() (assuming all the mutator methods do the same thing), but a Map which throws UnsupportedOperationException from the size() method would just be broken. If you're trying to implement a kind of map which doesn't know how big it is, you may be in trouble (although sometimes you can return Integer.MAX_VALUE).

Also note that the class documentation for UnsupportedOperationException says that it is part of the Java Collections Framework. Outside the collections framework, throwing UnsupportedOperationException is not be expected and could lead to client code that plain doesn't work. Sure, it's a RuntimeException, but just because you can throw it doesn't mean that your method will work if it always does.

Instead you could either refactor the interface (perhaps splitting it in two), or else rethink why this class is claiming to be a Foo when it plainly isn't, since it can't do the things that Foos are defined to be able to do.

Steve Jessop
+5  A: 

That read-only collection already provided by Java throw the UnsupportedOperationException during write operations is already an unfortunate design hack. The collection classes should have been written with separate read-only and write-only interfaces that are both inherited by the full read-write interface. Then you know what you're getting.

Jeff B
you'd still run into a problem where API's would require the read/write interface even in circumstances where a read-only would do. But I agree, the flexibility would be nice.
Mike Deck
This collections API would have ended up an unreadable mess, if this design decision had been taken.
oxbow_lakes
The problem in the specific case of Java comes not with the interfaces, but with AbstractCollection etc. You can't inherit from both AbstractROCollection and AbstractRWCollection, so the class hierarchy would be split in two at the top. Vector and ReadOnlyVector would be very distantly related.
Steve Jessop