【问题标题】:Extending a non-generic class to a generic class将非泛型类扩展为泛型类
【发布时间】:2011-08-28 19:22:00
【问题描述】:

org.apache.commons.collections.buffer 包中的 Java 类 CircularFifoBuffer 是非泛型的,可以存储任何类的对象。

我想创建一个这样的通用版本,它只能保存类 T 的对象。我的第一个想法是扩展 CircularFifoBuffer 并简单地编写一个新的“添加”方法:

public class CircularFifoQueue<T> extends CircularFifoBuffer {

    public boolean add(T data) {
        return super.add(data);
    }    

}

但是,这保留了旧的“添加”方法,允许添加任意类的对象。有没有办法使用继承而不是组合(这样我就不必重新实现 CircularFifoBuffer 的所有方法)但阻止该类的用户添加非 T 对象?

【问题讨论】:

    标签: java list collections queue


    【解决方案1】:

    您可以尝试以下方法。它不是很优雅,但它应该可以完成这项工作:

    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
    

    无论如何,实现一个委托其方法调用的类并不难。任何体面的 IDE 都会为您自动生成。

    【讨论】:

      【解决方案2】:

      一个想法是不要实现自己的缓冲区,只包装原始缓冲区:

      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
      }
      

      因此,内部缓冲区获取所有内容,但包装器确保只能添加​​ T 类型的对象。问题:现在缓冲区没有实现任何接口。所以它现在的使用有点受限(例如,如果您需要发送Buffer,则不能使用它)

      【讨论】:

      • 谢谢,这是我决定采用的解决方案。我还实现了Queue&lt;T&gt; 来访问这些方法。唯一的问题是我希望add(T t) 方法返回从队列末尾掉线的对象,而这在Queue&lt;T&gt; 接口的范围内似乎是不可能的。目前我刚刚创建了一个新方法addAndRetrieve(T t),它可以满足我的需求,尽管我很想听听其他解决方案。
      • 好一个!我也希望 CircularFifoQueue 实现队列。
      【解决方案3】:

      @Vivien 的回答已经解释了为什么这样做没有意义(有关更多信息,请阅读Liskov substitution principle)。

      但是,您可以通过定义 add(Object) 的自定义覆盖来解决此问题,该覆盖只会在运行时引发异常。这不是一个非常优雅的解决方案,但如果您想要快速修复,那么可能就是这样。

      【讨论】:

        【解决方案4】:

        不,你不能。

        这不可能的简单原因是多态性。如果您可以删除 add(Object) 方法,您将破坏 CircularFifoBuffer 类的多态性。

        这是一个简单的例子。要使其正常工作,您的 CircularFifoQueue 类需要有一个 add(Object) 方法。

        CircularFifoBuffer buffer = new CircularFifoQueue<String>();
        buffer.add(new Object());
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-24
        • 1970-01-01
        • 1970-01-01
        • 2011-08-09
        • 1970-01-01
        相关资源
        最近更新 更多