scala中有没有办法调用属于某个类型的方法?例如,假设我有一个名为Constructable
的特征,它描述的类型可以构建自己的默认实例。然后,我可以编写以下代码:
trait Constructable[A] {
def construct: A
}
class Foo(x: Int) extends Constructable[Foo] {
def construct = new Foo(0)
}
def main(args: Array[String]) {
val f = new Foo(4)
println(f.construct)
}
这没关系,但我真正想要的是能够仅在给定对象类型的情况下构造默认对象。例如,假设我想接受一个可构造的列表,并在列表的开头添加一个默认对象:
def prependDefault1[A <: Constructable[A]](c: List[A]): List[A] = {
val h = c.head
h.construct :: c
}
以上代码有效,但仅限于c不为空。我真正喜欢的是写下面的内容:
def prependDefault2[A <: Constructable[A]](c: List[A]): List[A] = {
A.construct :: c
}
有没有办法实现这一点,可能是通过更改Constructable
的定义,以便construct
方法属于“类”而不是“实例”(使用Java术语) ?
答案 0 :(得分:4)
你不能这样做,但你可以使用类型类来做到这一点:
trait Constructable[A] {
def construct: A
}
// 'case' just so it's printed nicely
case class Foo(x: Int)
// implicit vals have to be inside some object; omitting it here for clarity
implicit val fooConstructable = new Constructable[Foo] {
def construct = new Foo (0)
}
def prependDefault2[A : Constructable](c: List[A]): List[A] = {
implicitly[Constructable[A]].construct :: c
}
然后:
scala> prependDefault2(Nil: List[Foo])
res7: List[Foo] = List(Foo(0))
最后一些评论:
Implicits必须存在于对象内。它可以找到三个地方:
object Constructable { implicit val fooConstructable = ...
(类型类特征的伴随对象)
object Foo { implicit val fooConstructable = ...
(我们实现类型类的类的伴随对象)
object SomethingElse { implicit val fooConstructable = ...
(一些随机无关的对象)
仅在最后一种情况下,您需要使用import SomethingElse._
才能使用隐式。