为什么 scala 需要存在类型来限制泛型绑定?
Why does scala require existential types to restrict a generic bound?
具有以下 class 层次结构:
trait Provider[A] {
def get(): Seq[A]
}
abstract class ProviderImpl[A] extends Provider[A] {
final override def get(): Seq[A] = Seq()
}
trait HasX {
def getX: Int
}
trait RefinedProvider[A <: HasX] extends Provider[A]
class TypedProviderImpl extends ProviderImpl[HasX] with RefinedProvider[HasX]
我希望能够做到这一点:
val provider: RefinedProvider[_] = new TypedProviderImpl()
provider.get() map (_.getX)
但它不起作用,因为 provider.get()
的 return 类型是 Seq[Any]
这对我来说似乎是错误的,因为它是 RefinedProvider
,所以 get()
应该 return 一个 Seq[_ <: HasX]
.
问题:我可以用存在类型解决这个问题,但为什么编译器不能为我强制执行这个问题?
val provider: RefinedProvider[T] forSome { type T <: HasX } = ...
这是因为您使用 通配符: _
来声明您的变量类型:val provider: RefinedProvider[_]
,_
表示 任何类型,你可以这样做:
val provider = new TypedProviderImpl() // the compiler and IDE will auto infer **provider** type
或
val provider: RefinedProvider[HasX] = new TypedProviderImpl() // explicitly provider type
Ticket SI-2385 表明这只是将 A[_]
解释为 A[T] forSome
{ type T >: Nothing <: Any }
的规范的一部分,并且尽可能不推断更严格的界限。有人可能想知道规范是否不应该更新。
Ticket SI-6169 似乎表明,如果推断出更严格的界限,某些事情将停止工作。我不确定如何以及为什么。
一个小的妥协是你可以缩短
val provider: RefinedProvider[T] forSome { type T <: HasX }
到
val provider: RefinedProvider[_ <: HasX]
具有以下 class 层次结构:
trait Provider[A] {
def get(): Seq[A]
}
abstract class ProviderImpl[A] extends Provider[A] {
final override def get(): Seq[A] = Seq()
}
trait HasX {
def getX: Int
}
trait RefinedProvider[A <: HasX] extends Provider[A]
class TypedProviderImpl extends ProviderImpl[HasX] with RefinedProvider[HasX]
我希望能够做到这一点:
val provider: RefinedProvider[_] = new TypedProviderImpl()
provider.get() map (_.getX)
但它不起作用,因为 provider.get()
的 return 类型是 Seq[Any]
这对我来说似乎是错误的,因为它是 RefinedProvider
,所以 get()
应该 return 一个 Seq[_ <: HasX]
.
问题:我可以用存在类型解决这个问题,但为什么编译器不能为我强制执行这个问题?
val provider: RefinedProvider[T] forSome { type T <: HasX } = ...
这是因为您使用 通配符: _
来声明您的变量类型:val provider: RefinedProvider[_]
,_
表示 任何类型,你可以这样做:
val provider = new TypedProviderImpl() // the compiler and IDE will auto infer **provider** type
或
val provider: RefinedProvider[HasX] = new TypedProviderImpl() // explicitly provider type
Ticket SI-2385 表明这只是将 A[_]
解释为 A[T] forSome
{ type T >: Nothing <: Any }
的规范的一部分,并且尽可能不推断更严格的界限。有人可能想知道规范是否不应该更新。
Ticket SI-6169 似乎表明,如果推断出更严格的界限,某些事情将停止工作。我不确定如何以及为什么。
一个小的妥协是你可以缩短
val provider: RefinedProvider[T] forSome { type T <: HasX }
到
val provider: RefinedProvider[_ <: HasX]