关于存在性类型的困惑不大。
这对我有用:
def valueOf(c: Class[_], name: String) {
type C = Class[T] forSome {type T <: Enum[T]}
Enum.valueOf(c.asInstanceOf[C], name)
}
但这不是:
def valueOf(c: Class[_], name: String) {
type T = T forSome {type T <: Enum[T]}
Enum.valueOf(c.asInstanceOf[Class[T]], name)
}
在我看来,这两种表达方式都等同于:
Enum.valueOf(z.asInstanceOf[Class[T] forSome {type T <: Enum[T]}], name)
但是Scala说这只是我的想法:
inferred type arguments [T] do not conform to method valueOf's type parameter bounds [T <: Enum[T]]
Enum.valueOf(c.asInstanceOf[Class[T]], name)
^
最佳答案
请考虑以下两个表达式之间的区别:
Enum.valueOf(x.asInstanceOf[Class[X] forSome { type X <: Enum[X] }], name)
和:
Enum.valueOf(x.asInstanceOf[Class[X forSome { type X <: Enum[X] }]], name)
现在考虑在每种情况下如何推断
T
的类型参数valueOf
。在第一种情况下,我们拥有一个X
,我们知道它是Enum[X]
的子类型,并且我们都已准备就绪。另一方面,在第二种情况下,T
必须是X forSome { type X <: Enum[X] }
,并且至关重要的是,该类型不是Enum[X forSome { type X <: Enum[X] }]
的子类型,因此我们没有满足T
的约束。问题在于您的第二个示例与后者等效。
作为注脚,如果
Enum
的类型参数是协变的,则此方法会很好地工作。请使用以下简化示例:trait Foo[A]
trait Bar[A]
def foo[A <: Bar[A]](f: Foo[A]) = f
def x: Foo[X] forSome { type X <: Bar[X] } = ???
def y: Foo[Y forSome { type Y <: Bar[Y] }] = ???
现在
foo(x)
将会编译,但是foo(y)
不会编译,就像在您的代码中一样。但是,请稍微更改Bar
:trait Foo[A]
trait Bar[+A]
def foo[A <: Bar[A]](f: Foo[A]) = f
def x: Foo[X] forSome { type X <: Bar[X] } = ???
def y: Foo[Y forSome { type Y <: Bar[Y] }] = ???
现在他们都将进行编译。我猜想这与我们对两个示例具有相同的直觉有很强的直觉有关。
作为另一个脚注(响应gzmo的comment below),请考虑以下内容:
scala> trait Foo[A <: Foo[A]]
defined trait Foo
scala> class MyFoo extends Foo[MyFoo]
defined class MyFoo
scala> val myFoo = new MyFoo
myFoo: MyFoo = MyFoo@3ee536d
scala> myFoo: (X forSome { type X <: Foo[X] })
res0: X forSome { type X <: Foo[X] } = MyFoo@3ee536d
scala> myFoo: Foo[MyFoo]
res1: Foo[MyFoo] = MyFoo@3ee536d
让我们假设
X forSome { type X <: Foo[X] }
是Foo[X forSome { type X <: Foo[X] }]
的子类型(暂时忽略后者甚至不是有效类型的事实)。然后,我们将能够编写以下代码:myFoo: Foo[X forSome { type X <: Foo[X] }]
但是
Foo
是不变的,因此,如果我们有一些东西既是Foo[A]
又是Foo[B]
的实例,那么A =:= B
一定是这种情况。但是MyFoo =:= (X forSome { type X <: Foo[X] })
绝对不是这种情况。不确定所有这些内容是否会引起混淆,但这就是我说服自己编译器知道它在做什么的方式。
关于scala - Scala中的现有类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18396572/