Spark Shell中使用:paste定义类与伴生对象出现类型不匹配问题
Spark Shell 1.6中
:paste与逐行输入的类型歧义问题解析 这个问题的核心根源在于Scala REPL(Spark Shell基于此构建)对不同输入方式的代码编译机制差异,具体来说:
1. 逐行输入的处理逻辑
当你逐行输入类和伴生对象的定义时,Scala REPL会把每一段代码都纳入同一个交互式会话的上下文里——所有定义都会被包裹在嵌套的$iw(交互式包装类)作用域中。后续的ls_i和ls_foo代码也会在这个连续的上下文里执行,所以所有代码引用的Foo5都是同一个类实例,类型完全匹配,自然不会出现错误。
2. :paste模式的处理逻辑
而使用:paste命令时,REPL会把你粘贴的整个代码块当作一个独立的编译单元来处理,编译后生成一个单独的包装类(比如$lineX.$read.$iw)。当你在paste之后再输入val ls_i和ls_foo的代码时,这些代码会被编译到全新的编译单元(对应另一个$lineY.$read.$iw包装类)中。
这时候就出现了关键问题:虽然两个地方的类名都叫Foo5,但它们的全限定类名完全不同(属于不同的包装类),在JVM看来是两个完全不同的类型。编译器报错时只显示短类名,所以你会看到看似矛盾的found: List[Foo5], required: List[Foo5]——本质是两个同名但不同的类型不匹配。
快速解决方法
如果你想用:paste加载代码,最简单的方式是把后续的执行代码也一起粘贴进去,让所有代码处于同一个编译单元中,这样所有Foo5的引用都会指向同一个类,就不会有类型歧义了。比如:
import scala.util.Try class Foo5(val i: Int) object Foo5Companion { def apply(i: Int): Foo5 = new Foo5(i) def apply(d: Double): Foo5 = new Foo5(d.toInt) def applyTry(i: Int): Try[Foo5] = Try { apply(i) } def applyTry(d: Double): Try[Foo5] = Try { apply(d) } } val ls_i: List[Int] = List(1,2,3) val ls_foo: List[Foo5] = ls_i.map(Foo5Companion.apply)
内容的提问来源于stack exchange,提问作者kmh
相关产品推荐
相关产品推荐

