scala – 案例类和特征线性化
假设我想写一个case class Stepper,如下所示:
case class Stepper(step: Int) {def apply(x: Int) = x + step} 它附带了一个很好的toStringimplementation: scala> Stepper(42).toString res0: String = Stepper(42) 但它并不是一个功能: scala> Some(2) map Stepper(2) <console>:10: error: type mismatch; found : Stepper required: Int => ? Some(2) map Stepper(2) 解决方法是实现“功能特征” case class Stepper(step: Int) extends (Int => Int) {def apply(x: Int) = x + step} 但是,我不能再有一个很好的toString实现了: scala> Stepper(42).toString res2: java.lang.String = <function1> 那么问题是:我可以有这两个世界的最好吗?有没有一个解决方案,我有一个很好的toString实现免费和一个trait功能的实现.换句话说,有没有一种方法来应用线性化,最终应用案例类的语法糖? 解决方法
这个问题不是与线性化有关.在case-classes toString是由编译器自动生成的方法,当且仅当在最终类型中不覆盖Any.toString时.
但是,答案部分与线性化有关 – 我们需要使用由编译器生成的方法来覆盖Function1.toString,如果不是由Function1引入的版本: trait ProperName extends Product { override lazy val toString = scala.runtime.ScalaRunTime._toString(this) } // now just mix in ProperName and... magic! case class Stepper(step: Int) extends (Int => Int) with ProperName { def apply(x:Int) = x+step } 然后 println(Some(2) map Stepper(2)) println(Stepper(2)) 会生产
更新 以下是一个不依赖于未记录的API方法的ProperName trait的版本: trait ProperName extends Product { override lazy val toString = { val caseFields = { val arity = productArity def fields(from: Int): List[Any] = if (from == arity) List() else productElement(from) :: fields(from + 1) fields(0) } caseFields.mkString(productPrefix + "(",",")") } } 替代toString实现是从原始_toString方法 请注意,这个替代实现仍然是基于一个case类总是扩展Product trait的假设.虽然后者与Scala 2.9.0一样,但事实上已被Scala社区的一些成员所了解和依赖,但并没有正式记录为Scala Language Spec的一部分. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |