【问题标题】:Java factory inheritance with generic interface implementation具有通用接口实现的 Java 工厂继承
【发布时间】:2021-01-24 17:09:06
【问题描述】:

我希望有一个工厂继承另一个工厂,两个工厂都实现相同的通用接口,但类型不同,彼此继承:

class FactoryA implements FactoryI<A> {
    // common code
    ...
    A get() {
        return new A();
    }
}

class FactoryB extends FactoryA implements FactoryI<B> {
    B get() {
        return new B();
    }
}

class B extends A {
}

FactoryI<T> {
    T get()
}

但这给了我以下编译错误:

'FactoryI' cannot be inherited with different type arguments: 'A' and 'B'

我的第一个版本没有从 FactoryA 继承 FactoryB,这工作正常。 但事实证明,现在两个工厂之间有我想要重用的通用代码。

实现这一目标的最佳方法是什么?

【问题讨论】:

    标签: java inheritance interface factory


    【解决方案1】:

    您还需要将FactoryA 设为通用。这样子类可以返回A的不同子类

    class FactoryA<T extends A> implements FactoryI<T> {
        // common code
        public T get() {
            return (T) new A();
        }
    }
    
    class FactoryB extends FactoryA<B> {
        public B get() {
            return new B();
        }
    }
    
    class A {
    
    }
    
    class B extends A {
    }
    
    interface FactoryI<T> {
        T get();
    }
    

    【讨论】:

    • 未经检查的类型转换应该让您感到震惊。您现在可以写FactoryA&lt;B&gt; f = new FactoryA&lt;&gt;(); 而不会出错。此实例化甚至不会引发警告,因为导致警告的有问题的代码位于 get() 方法中。
    • @Holger 有可能滥用这种模式,但是,如果你滥用了第一次测试它,它就会爆炸。这确实需要被调用者正确处理,但调用者不需要知道任何特殊情况。
    • 问题在于它不会FactoryA&lt;B&gt; f = new FactoryA&lt;&gt;(); 处爆炸,甚至不能保证在稍后调用get() 时爆炸,因为该呼叫可能也在通用代码中。它爆炸的地方是否与FactoryA的实例化有明显联系,是不可预测的。好吧,即使有,实例化也没有错。就是FactoryA的实现。
    • 您可以轻松制作干净的解决方案,class FactoryA { /* common code */ public A get() { return new A(); } public static final FactoryI&lt;A&gt; FACTORY_A = new FactoryA()::get; }class FactoryB extends FactoryA { @Override public B get() { return new B(); } public static final FactoryI&lt;B&gt; FACTORY_B = new FactoryB()::get; }
    猜你喜欢
    • 2021-03-17
    • 2015-08-03
    • 2021-01-29
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 1970-01-01
    • 2019-03-06
    • 1970-01-01
    相关资源
    最近更新 更多