Java 带通配符的模板继承
Java template inheritance with wildcard
在 Java 中,以下代码无法编译:
class Pair <T1> { }
class Real {
Pair<Real> sqrt() {
return null;
}
}
class Complex extends Real {
Pair<Complex> sqrt() {
return null;
}
}
有道理,因为 Pair<Complex>
没有继承自 Pair<Real>
。
然而,我惊讶地发现这段代码可以编译:
class Pair <T1> { }
class Real {
Pair<? extends Real> sqrt() {
return null;
}
}
class Complex extends Real {
Pair<? extends Complex> sqrt() {
return null;
}
}
这似乎暗示 Pair<? extends Complex>
实际上继承自 Pair<? extends Real>
谁能解释一下?这里到底发生了什么?
我认为最好的思考方式是:
您需要在 Complex
中提供一个 return 类型 Pair<T>
的方法,其中 T
可以是从 [=14= 继承的任何东西].您的 Complex
实现将 return 类型要求更改为 Pair<U>
,其中 U
可以是从 Complex
.
继承的任何内容
然而,由于 Complex
继承自 Real
,任何扩展 Complex
的内容也将扩展 Real
,因此您仍然提供一种方法来保证 return Pair<T>
.
类型
形式化一点:
Pair<? extends Complex> ≡ Pair<? extends Complex extends Real> ≡ Pair<? extends Real>
第一个未编译示例的不同之处在于,您的 Complex
实现实际上限制了 return 类型,因为并非每个 Pair<Real>
都是 Pair<Complex>
.
恕我直言,Angelika Langer 为您的问题提供了最好的 explanation (see also subsequent answers),但又困难又详尽。
此外,当不确定两种类型是否真的是子类型和超类型时,以下辅助方法对我很有用。该方法不打算运行。只需显式键入通用参数并查看它是否编译。
public <T,U extends T> void m() {}
this.<Set<Object>,Set<Integer>>m(); -- wont compile
this.<Set<? extends Object>,Set<? extends Integer>>m(); -- compiles
在 Java 中,以下代码无法编译:
class Pair <T1> { }
class Real {
Pair<Real> sqrt() {
return null;
}
}
class Complex extends Real {
Pair<Complex> sqrt() {
return null;
}
}
有道理,因为 Pair<Complex>
没有继承自 Pair<Real>
。
然而,我惊讶地发现这段代码可以编译:
class Pair <T1> { }
class Real {
Pair<? extends Real> sqrt() {
return null;
}
}
class Complex extends Real {
Pair<? extends Complex> sqrt() {
return null;
}
}
这似乎暗示 Pair<? extends Complex>
实际上继承自 Pair<? extends Real>
谁能解释一下?这里到底发生了什么?
我认为最好的思考方式是:
您需要在 Complex
中提供一个 return 类型 Pair<T>
的方法,其中 T
可以是从 [=14= 继承的任何东西].您的 Complex
实现将 return 类型要求更改为 Pair<U>
,其中 U
可以是从 Complex
.
然而,由于 Complex
继承自 Real
,任何扩展 Complex
的内容也将扩展 Real
,因此您仍然提供一种方法来保证 return Pair<T>
.
形式化一点:
Pair<? extends Complex> ≡ Pair<? extends Complex extends Real> ≡ Pair<? extends Real>
第一个未编译示例的不同之处在于,您的 Complex
实现实际上限制了 return 类型,因为并非每个 Pair<Real>
都是 Pair<Complex>
.
恕我直言,Angelika Langer 为您的问题提供了最好的 explanation (see also subsequent answers),但又困难又详尽。
此外,当不确定两种类型是否真的是子类型和超类型时,以下辅助方法对我很有用。该方法不打算运行。只需显式键入通用参数并查看它是否编译。
public <T,U extends T> void m() {}
this.<Set<Object>,Set<Integer>>m(); -- wont compile
this.<Set<? extends Object>,Set<? extends Integer>>m(); -- compiles