问题
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 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?
回答1:
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)
回答2:
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());
回答3:
@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.
回答4:
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.
来源:https://stackoverflow.com/questions/6057826/extending-a-non-generic-class-to-a-generic-class