【发布时间】:2014-06-09 07:12:43
【问题描述】:
考虑以下类,我认为它被正确称为self-typed 类:
public abstract class Example<E extends Example<E>> {
/** Constructs an instance of the subclass */
protected abstract E construct();
/** Do a private operation in the base class */
private void specialOp() {}
public E get1() {
E obj = construct();
// Error: The method specialOp() from the type Example<E> is not visible
obj.specialOp();
return obj;
}
public E get2() {
Example<E> obj = construct();
obj.specialOp();
// Warning: Type safety: Unchecked cast from Example<E> to E
return (E)obj;
}
public E get3() {
E obj = construct();
((Example<E>)obj).specialOp();
return obj;
}
}
也就是说,扩展这个类的实现会有这样的类型签名:
public class SubExample extends Example<SubExample>
三个get*() 方法中的每一个表面上都做同样的事情——构造Example 的子类,在实例上执行私有方法,并将其作为子类型返回。然而,只有最后一个示例编译时没有警告。
get1() 中的行为即使没有泛型也是错误的,请考虑:
public class Example {
private void specialOp() {};
public void get(SubExample e) {
// Error: The method specialOp() from the type Example is not visible
e.specialOp();
}
public static class SubExample extends Example {}
}
我理解,即使它对我来说似乎是不必要的限制。同样get3() 是有道理的,尽管我不喜欢需要这样投射。但是get2() 让我很困惑。我知道E 在技术上是Example<E> 的子类型,但是这个泛型的边界不能确保所有Example<E>s 也是Es 吗?如果是这样,为什么这样投射不安全?是否可以在没有警告的情况下从Example<E> 转换为E?
【问题讨论】:
-
是否可以将
List<Integer>转换为Integer? -
使
specialOp方法受保护而不是私有。 -
@alfasin since
E extends Example<E>是的,可能将Example<E>转换为E。自类型签名旨在保证所有E,但我不确定这是否属实。 -
@Henry 谢谢,是的,这将解决编译问题。但这不是我的问题。
-
我接受的答案提供了一个反例,并证明引用“必须相同”是不正确的。