通用接口和协方差

时间:2016-06-15 13:21:55

标签: java generics

以下代码运行良好:

public class ICopyableTest {

    private interface ICopyable<T extends ICopyable<? extends T>> {
        void copyFrom(T original);
    }

    private interface IVal<T> extends ICopyable<IVal<? extends T>> {
        T getV();
    }

    private static class Val<T> implements IVal<T> {
        private T v;

        public T getV() {
            return v;
        }

        public Val(final T v) {
            this.v = v;
        }

        @Override public void copyFrom(final IVal<? extends T> original) {
            v = original.getV();
        }
    }

    private static class StrVal extends Val<String> {
        public StrVal(final String v) {
            super(v);
        }
    }


    public static void main(String[] args) {
        Val<Object> o1 = new Val<>(new Object());
        Val<String> o2 = new Val<>("qwe");

        StrVal o3 = new StrVal("zxc");

        o1.copyFrom(o2); // that's the point
        o1.copyFrom(o3);

        o2.copyFrom(o3);
        o3.copyFrom(o2);

        Val<Object> toObj = (Val<Object>) (Val<?>) o2; // [1]
    }
}

基本上我有ICopyable接口提供复制功能,IVal增加了上面的存储空间,以及两个实现Val的示例类。 <? extends T>的要点是为CopyFrom方法提供协变参数,因此您可以执行o1.copyFrom(o2)等。 所以一切正常我猜。

现在假设我想在ICopyable或IVal类上进行另一个参数设置:

private static class Bla<T extends ICopyable<T>> {
    final T value1;
    final T value2;

    public Bla(final T value1, final T value2) {
        this.value1 = value1;
        this.value2 = value2;
    }

    void letsCopy() {
        value1.copyFrom(value2);
        value2.copyFrom(value1);
    }
}

现在为什么我不能用以下任何一个实例化它?

new Bla<StrVal>(o3, o3);
new Bla<Val<Object>>(o1, o1);
new Bla<Val<String>>(o2, o2);

说实话,我自己有点失落,这就是我探索它的原因。还有一个非常重要的问题,即为什么使用仿制药是如此耗尽,甚至在使用java工作5年以后,我无法在没有半小时冥想的情况下找出那些东西 - 我只是愚蠢吗?

我只想拥有一个参数化类,它允许我使用IVal / ICopyable值,请注意它应该是参数化类,而不是单独的方法,因此您可以将这些值的实例存储在字段中,例如。

1 个答案:

答案 0 :(得分:0)

我会这样做的

public class Test {

    interface Copyable<T> {
        void copyFrom(Copyable<T> v);
        T getV();
    }

    interface Val<T> extends Copyable<T> {
        // Do not know if this is usefull
    }

    abstract class AbstractVal<T> implements Val<T> {
        T value;
        public AbstractVal(T val) {
            this.value = val;
        }
    }

    class StrVal extends AbstractVal<String> {

        public StrVal(String o3) {
            super(o3);
        }

        @Override
        public void copyFrom(Copyable<String> v) {
            this.value = v.getV();
        }

        @Override
        public String getV() {
            return this.value;
        }
    }

    class Bla<T extends AbstractVal<S>, S> {
        final T value1;
        final T value2;

        public Bla( T value1,  final T value2) {
            this.value1 = value1;
            this.value2 = value2;
        }

        void letsCopy() {
            value1.copyFrom(value2);
        }
    }

    void test() {
        StrVal o1 = new StrVal("qwe");
        StrVal o2 = new StrVal("qwe2");
        StrVal o3 = new StrVal("zxc");
        Bla tester = new Bla<StrVal, String>(o1, o2);
        tester.letsCopy();
        System.out.println(tester.value1.getV());
    }

    public static void main(String[] args) {
        Test t = new Test();
        t.test();
    }
}

对于它所做的事情可能有点复杂,但我认为这是一个想法..