Extending a non-generic class to a generic class
The Java class CircularFifoBuffer in the package org.apache.commons.collections.buffer is non-generic, and can store objects of any class.
I would like to create a generified version of this, that can only hold objects of class T. My first thought was to extend CircularFifoBuffer and simply write a new 'add' method:
public class CircularFifoQueue<T> extends CircularFifoBuffer {
public boolean add(T data) {
return super.add(data);
}
}
However, this leaves the old 'add' method in place, allowing for objects of arbitrary class to be added. Is开发者_JAVA百科 there a way around this that uses inheritance rather than composition (so that I don't have to re-implement all of CircularFifoBuffer's methods) but prevents users of the class from adding non-T objects?
One idea is t implement your own buffer that just wraps the original one:
public class CircularFifoQueue<T> {
private CircularFifoBuffer buffer = new CircularFifoBuffer();
public boolean add(T data) {
return buffer.add(data);
}
// implement all other methods that are needed
}
So the internal buffer takes everything but the wrapper makes sure that only T
type objects can be added. Problem: right now the buffer does not implement any interface. So it's usage is a bit limited right now (you can't use it if you need to send a Buffer
for example)
No, you can't.
The simple reason why this isn't possible is polymorphism. If you could remove the add(Object)
method, you would break polymorphism for the CircularFifoBuffer
class.
Here is a simple example. For this to work correctly, your CircularFifoQueue
class needs to have a add(Object)
method.
CircularFifoBuffer buffer = new CircularFifoQueue<String>();
buffer.add(new Object());
@Vivien's answer already explains why it doesn't really make sense to do this (for more information, read about the Liskov substitution principle).
However, you could hack around this by defining a custom override of add(Object)
that simply throws an exception at run-time. It's not a very elegant solution, but if you want a quick fix, then this might be it.
You can try the following approach. It is not very elegant, but it should do the job:
public class CircularFifoQueue<T> extends CircularFifoBuffer {
private Class<T> klass;
public CircularFifoQueue(Class<T> klass) {
this.klass = klass;
}
@Override
public boolean add(Object data) {
T typedData = klass.cast(data);
return super.add(typedData);
}
public boolean add(T data) {
return super.add(data);
}
}
...
CircularFifoQueue<String> queue = new CircularFifoQueue<String>(String.class);
queue.add("hello"); // should work
queue.add(123L); // should throw ClassCastException
Anyway, implementing a class that delegates its method calls is not very hard. Any decent IDE will autogenerate that for you.
精彩评论