我有代码定义特征的类型别名和该类型别名的单例对象。在尝试使用REPL中的这些时,我会遇到一些令人惊讶的错误。
这是我能够重现问题的最小代码量。请注意,将所有内容拆分为不同的文件非常重要,将所有内容放在一起似乎可以解决问题。
Decoder.scala
package foo
trait Decoder[E, D] {
def decode(e: E): D
}
package.scala
package object foo {
type StringDecoder[A] = Decoder[String, A]
}
StringDecoder.scala
package foo
object StringDecoder {
def apply[A](f: String => A): StringDecoder[A] = new StringDecoder[A] { override def decode(s: String) = f(s) }
def apply[A](implicit da: StringDecoder[A]): StringDecoder[A] = da
def foobar: Unit = println("foobar")
}
以下是展示问题的示例REPL会话:
scala> import foo._
import foo._
scala> implicit val test: StringDecoder[Float] = StringDecoder(_.toFloat)
test: foo.StringDecoder[Float] = foo.StringDecoder$$anon$1@40a4337a
scala> StringDecoder.foobar
<console>:15: error: value foobar is not a member of object foo.StringDecoder
StringDecoder.foobar
另一方面,如果我不首先引用类型别名,它可以正常工作:
scala> import foo._
import foo._
scala> StringDecoder.foobar
foobar
我目前的解释是,当前者在前者之前被引用时,对象在某种程度上被类型别名所遮蔽,但我真的想不出为什么会发生这种情况。我也没有在REPL之外(或tut之外,基本上是REPL)重现这个问题。
这种行为是否有任何已知的解释?
答案 0 :(得分:4)
有没有已知的解释?不是,但这是一个已知问题(SI-7139)。
在关于该问题的评论中,Jason Zaugg提出了一种解决方法,这意味着将StringDecoder
更改为类似的内容:
package foo
object StringDecoder0 {
...
}
然后:
package object foo {
type StringDecoder[A] = Decoder[String, A]
val StringDecoder: StringDecoder0.type = StringDecoder0
}
这不是一个正式的伴侣对,但它支持预期的用法(只要你没有在StringDecoder0
中定义隐式实例)。