Scala:没有明确的类型参数的Typecast
请考虑以下示例:
case class C[T](x:T) { def f(t:T) = println(t) type ValueType = T } val list = List(1 -> C(2),"hello" -> C("goodbye")) for ((a,b) <- list) { b.f(a) } 在这个例子中,我知道(运行时保证)一个类型将是一些T,而b将具有相同T的类型C [T].当然,编译器不知道,因此我们得到一个输入错误BF(a)中. 要告诉编译器这个调用是OK的,我们需要做一个类型转换àla b.f(a.asInstanceOf [T]).不幸的是,T在这里是不知道的.所以我的问题是:如何重写b.f(a)以使此代码编译? 我正在寻找一个不涉及复杂构造(保持代码可读)的解决方案,而且这是一个“干净”的意思,我们不应该依赖代码删除来使其工作(请参阅下面的第一种方法). 我有一些工作方法,但是由于各种原因我觉得他们不满意. 我试过的方法 b.asInstanceOf[C[Any]].f(a) 这是有用的,并且是可读的,但它是基于“谎言”. b不是C [Any]类型,我们没有得到运行时错误的唯一原因是因为我们依赖于JVM的限制(类型擦除).我认为只有使用x.asInstanceOf [X]才是很好的风格,当我们知道x真的是X型. b.f(a.asInstanceOf[b.ValueType]) 这应该是根据我对类型系统的理解而工作的.我已经将成员ValueType添加到C类,以便能够明确地引用类型参数T.然而,在这种方法中我们得到一个神秘的错误信息: Error:(9,22) type mismatch; found : b.ValueType (which expands to) _1 required: _1 b.f(a.asInstanceOf[b.ValueType]) ^ 为什么?似乎抱怨我们期望类型_1,但得到类型_1! (但是即使这种方法有效,它也限于我们有可能将成员ValueType添加到C的情况.如果C是一些现有的库类,那么我们也不能这样做). for ((a,b) <- list.asInstanceOf[List[(T,C[T]) forSome {type T}]]) { b.f(a) } 这一个工作,并且语义正确(即,当调用asInstanceOf时,我们不会“说谎”).限制是这有点不可读.此外,它对当前情况有些具体:如果a,b不是来自同一个迭代器,那么我们可以在哪里应用此类型转换? (此代码也对Intelli / J IDEA 2016.2过于复杂的副作用,它将其显示为编辑器中的错误.) val (a2,b2) = (a,b).asInstanceOf[(T,C[T]) forSome {type T}] b2.f(a2) 我会期望这个工作,因为a2,b2现在应该有类型T和C [T]相同的存在T.但我们得到一个编译错误: Error:(10,9) type mismatch; found : a2.type (with underlying type Any) required: T b2.f(a2) ^ 为什么? (除此之外,这种方法的缺点是由于一对的创建和销毁而导致运行时费用(我认为).) b match { case b : C[t] => b.f(a.asInstanceOf[t]) } 这个工作.但是使用匹配来封装代码可使代码的可读性变得更差. (对于Intelli / J来说也是太复杂了) 解决方法
最干净的解决方案是IMO,您使用类型捕获模式匹配发现的解决方案.您可以通过将模式直接集成在您的理解中,使其简洁明了,并希望可读,如下所示:
for ((a,b: C[t]) <- list) { b.f(a.asInstanceOf[t]) } 小提琴:http://www.scala-js-fiddle.com/gist/b9030033133ee94e8c18ad772f3461a0 如果你不是在理解,不幸的是,相应的模式分配不起作用: val (c,d: C[t]) = (a,b) d.f(c.asInstanceOf[t]) 这是因为在第二行,t不再是范围了.在这种情况下,您必须使用完整的模式匹配. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |