通用斯卡拉
收集的类型在斯卡拉2.9.1通用斯卡拉
随着
def collectFirstOfT[T](la: List[_])(implicit m:Manifest[T]) : Option[T] = {
la.collect{case x if m.erasure.isAssignableFrom(x.getClass) => x}.
headOption.asInstanceOf[Option[T]]}
class A
class B
为什么这样表达:
val oB:Option[B] = collectFirstOf(List(new A,new B))
编译但收集一些(A),但
val oB =collectFirstOf[B](List(new A,new B))
工作正常。
如何从Option [T]推断T?
你必须要在下面的行看作两个独立的部分,=的左侧和右侧:
val oB: Option[B] = collectFirstOf(List(new A,new B))
什么你期待在这里的是,collectFirstOf表达的类型(应该从值的类型推断出右值)。编译器不能这样做。你必须具体说明你期望的类型。以下例子:
val v: Long = 1 + 4
表达式1 + 4的类型是一个Int。这个int然后被转换成一个Long。编译器没有,也不能推断出你想让1或4变长:
所以,要解决你的问题,你需要告诉编译器你期望的类型,否则它会假设java.lang.Object:
val oB = collectFirstOf[B](List(new A,new B))
因此,清单被正确赋值,并且与世界一切都很好。那么,为什么以下甚至编译:
val oB:Option[B] = collectFirstOfT(List(new A,new B))
oB: Option[B] = Some([email protected])
乍一看,它似乎并不像这应该工作,但它确实。这是因为collectFirstOfT实际上返回一个选项[没有],它可以安全地转换成选项[B]:
scala> val f = collectFirstOfT(List(new A,new B))
f: Option[Nothing] = Some([email protected])
scala> f.asInstanceOf[Option[B]]
res4: Option[B] = Some([email protected])
因为编译器无法从agruments中推断出T
,所以您必须明确写出它。在第一种情况下,collect
接受所有列表。
'T'(或'Option [T]')只适用于返回类型。 '{case x if m.erasure.isAssignableFrom(x.getClass)=> x}'是一个'PartialFunction [-Any,+ Any]'。 – jwinandy 2012-04-12 12:33:30
此:
val oB:Option[B] = collectFirstOfT(List(new A,new B))
等效于此:
val oB:Option [B] = collectFirstOfT [Nothing](List(new A,new B))
由于Nothing
是所有内容的子类,因此它可以从A
指定。唉,它也可从B
转让,这意味着您可以将Option[Nothing]
分配给Option[B]
。
有趣的事实:这是真的,因为Option
是co-variant。如果不是,那么T
将不得不推断为B
,这将使其工作。
有趣的事实2:此代码不会在昨天的主干上编译。
漂亮!我怎样才能防止功能被误用? (Idealy,它不应该编译) – jwinandy 2012-04-12 13:10:11
一个简单快捷的方法是添加一个显式参数,类:collectFirstOfT [T](cls:Class [T],la:List [_]),然后调用如下所示: collectFirstOfT(classOf [B],List(new A,new B))。这将按预期返回选项[B]。 – 2012-04-12 13:38:45