Extending a non-generic class to a generic class

核能气质少年 提交于 2020-01-04 14:29:39

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!