【问题标题】:Call a "static" method belonging to a generic type in scala在scala中调用属于泛型类型的“静态”方法
【发布时间】:2014-05-22 23:43:04
【问题描述】:

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

【问题讨论】:

  • 我想知道这是否是隐式参数的一种候选用法(因此可以传递工厂对象,而无需明确说明)。这是合理的,还是完全错误的?
  • Scala 有静态方法,但就像在 java 中一样,它们不参与继承

标签: scala


【解决方案1】:

你不能这样做,但你可以使用类型类来做到这一点:

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))

一些最后的评论:

隐式必须存在于对象中。它可以位于三个位置:

  • object Constructable { implicit val fooConstructable = ...(类型类特征的伴随对象)

  • object Foo { implicit val fooConstructable = ...(我们为其实现 typeclass 的类的伴随对象)

  • object SomethingElse { implicit val fooConstructable = ...(一些随机的无关对象)

只有在最后一种情况下,您才需要使用 import SomethingElse._ 才能使用隐式。

【讨论】:

  • 太棒了!这种方法和使用隐式参数有什么区别(即定义def prependDefault1[A](c: List[A])(implicit f: Contructable[A])...
  • 唯一的区别是语法;它被编译器视为完全相同的东西。选择你喜欢的那个。
猜你喜欢
  • 2015-03-09
  • 1970-01-01
  • 1970-01-01
  • 2012-02-10
  • 2010-09-16
  • 2011-07-14
  • 2017-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多