Java OOP – Using Empty Interface to Combine Multiple Interfaces

javaobject-oriented

Suppose you have two interfaces:

interface Readable {
    public void read();
}

interface Writable {
    public void write();
}

In some cases the implementing objects can only support one of these but in a lot of cases the implementations will support both interfaces. The people who use the interfaces will have to do something like:

// can't write to it without explicit casting
Readable myObject = new MyObject();

// can't read from it without explicit casting
Writable myObject = new MyObject();

// tight coupling to actual implementation
MyObject myObject = new MyObject();

None of these options is terribly convenient, even more so when considering that you want this as a method parameter.

One solution would be to declare a wrapping interface:

interface TheWholeShabam extends Readable, Writable {}

But this has one specific problem: all implementations that support both Readable and Writable have to implement TheWholeShabam if they want to be compatible with people using the interface. Even though it offers nothing apart from the guaranteed presence of both interfaces.

Is there a clean solution to this problem or should I go for the wrapper interface?

UPDATE

It is in fact often necessary to have an object that is both readable and writable so simply seperating the concerns in the arguments is not always a clean solution.

UPDATE2

(extracted as answer so it's easier to comment on)

UPDATE3

Please beware that the primary usecase for this is not streams (although they too must be supported). Streams make a very specific distinction between input and output and there is a clear separation of responsibilities. Rather, think of something like a bytebuffer where you need one object you can write to and read from, one object that has a very specific state attached to it. These objects exist because they are very useful for some things like asynchronous I/O, encodings,…

UPDATE4

One of the first things I tried was the same as the suggestion given below (check the accepted answer) but it proved to be too fragile.

Suppose you have a class that has to return the type:

public <RW extends Readable & Writable> RW getItAll();

If you call this method, the generic RW is determined by the variable receiving the object, so you need a way to describe this var.

MyObject myObject = someInstance.getItAll();

This would work but once again ties it to an implementation and may actually throw classcastexceptions at runtime (depending on what is returned).

Additionally if you want a class variable of the type RW, you need to define the generic at the class level.

Best Answer

Yes, you can declare your method parameter as an underspecified type that extends both Readable and Writable:

public <RW extends Readable & Writable> void process(RW thing);

The method declaration looks terrible, but using it is easier than having to know about the unified interface.