拨打"静电"属于scala中的泛型类型的方法

时间:2014-05-22 23:43:05

标签: scala

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术语) ?

1 个答案:

答案 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._才能使用隐式。