繁体   English   中英

覆盖泛型返回类型的方法

[英]Overriding method with generic return type

假设我有一个定义以下抽象方法的超类

public abstract <T extends Interface> Class<T> getMainClass();

现在,如果我想在某些子类中覆盖它

public Class<Implementation> getMainClass(){
    return Implementation.class;
}

我收到有关类型安全和未选中转换的警告:

类型安全:返回类型Class<Implementation>getMainClass()从类型SubFoo需要未经检查的转换,以符合Class<Interface>从类型SuperFoo

如果<T extends Interface> Class<Implementation>是否属于Class<T> <T extends Interface> 有没有办法正确摆脱警告?

重写方法的返回类型必须是重写方法的返回类型的子类型。

Class<Impl>不是Class<T>的子类型,其中<T extends Interface> T在这里不得而知。

Class<Impl>Class<? extends Interface>的子类型Class<? extends Interface> 根据子类型规则Class<? extends Interface>


关于通配符的一些子类型规则:

适用于任何类型X.

  • A<X>A<? extends X>的子类型A<? extends X> A<? extends X>

  • A<X>A<? super X>的子类型A<? super X> A<? super X>

如果ST子类型

  • A<? extends S> A<? extends S>A<? extends T>的子类型A<? extends T> A<? extends T>

  • A<? super T> A<? super T>A<? super S>的子类型A<? super S> A<? super S>

更简洁,( <:表示“是”的子类型“)

A<S>    <:    A<? extends S>    <:    A<? extends T>

A<T>    <:    A<?  super  T>    <:    A<?  super  S>

请考虑以下类似于您的方案:

public class SuperFoo {
     public abstract <T extends Interface> List<T> getList();
} 

public class SubFoo extends SuperFoo {
     private List<Implementation> l = new ArrayList<Implementation>();

     public List<Implementation> getList() {
          return l;
     }

     public void iterate() {
          for (Implementation i: l) ...;
     }
}

SubFoo subFoo = new SubFoo();
SuperFoo superFoo = subFoo;
superFoo.getList().add(new AnotherImplementation()); // Valid operation!
subFoo.iterate(); // Unexpected ClassCastException!

在这种情况下,未经检查的转换警告会警告您可能出现意外的ClassCastException

但是,在你的情况下,当返回类型是Class<...> ,它不是问题(据我所知),所以你可以合法地抑制警告:

@SuppressWarnings("unchecked")
public Class<Implementation> getMainClass(){ ... }  

另一种选择是使SuperFoo本身具有通用性:

public class SuperFoo<T extends Interface> {
    public abstract Class<T> getMainClass(); 
}

public class SubFoo extends SuperFoo<Implementation> {
    public Class<Implementation> getMainClass() { ... }
}

对于另一个(也许是最好的)选项,请参阅Stas Kurilin的回答。

尝试这个

public abstract Class<? extends Interface> getMainClass();

通过这样的警告重新组织的例子 java尝试防止像这样的情况

class OtherImpl implements Interface{ 
} 
A a = new B();//where A - your abstract class and B - implementation
Class<OtherImpl> other = a.<OtherImpl>getMainClass();//some broken think, But _without_ runtime exception

正如@axtavt提到的例子被打破了。 我重组了它。

为什么你想要像public abstract Class<? extends Interface> getMainClass(); public abstract Class<? extends Interface> getMainClass(); 而不是public abstract Interface getMainClass();

我想你可以简单地返回一个Interface实例,然后,如果调用者想要访问底层运行时类,只需在返回的对象上调用getClass()即可。

从本质上讲,我认为你可以做到

public InterfaceImpl implements Interface {
    // ...
};

public abstract class A {
    public abstract Interface getMainClass();
    // ...
}

public class AImpl {
    return new InterfaceImpl();
}

public class Main {
    public static void main(String[] args) {
        AImpl aImpl = new AImpl();
        Interface i = aImpl.getMainClass();
        System.out.println(i.getClass());
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM