The*_*ect 7 scala traits self-type case-class
我有一些case类,它们的tupled伴随对象中定义了一个方法.从下面的代码对象中可以看出,它只是代码重复.
case class Book(id: Int, isbn: String, name: String)
object Book {
def tupled = (Book.apply _).tupled // Duplication
}
case class Author(id: Int, name: String)
object Author {
def tupled = (Author.apply _).tupled // Duplication
}
Run Code Online (Sandbox Code Playgroud)
从另一个问题(scala自我类型可以强制执行案例类类型),似乎我们不能强制将特征的自我类型作为案例类.
有没有办法定义一个Tupled可以应用如下的特征(比如说)?
// What would be value of ???
trait Tupled {
self: ??? =>
def tupled = (self.apply _).tupled
}
// Such that I can replace tupled definition with Trait
object Book extends Tupled {
}
Run Code Online (Sandbox Code Playgroud)
Tra*_*own 12
因为FunctionNScala中的类型之间没有关系,所以如果没有arity级别的样板,就不可能做到这一点 - 没有办法在apply不枚举所有可能数量的成员的情况下抽象同伴对象的方法.
你可以用一堆CompanionN[A, B, C, ...]特性手工完成这个,但这很烦人.Shapeless提供了更好的解决方案,允许您编写如下内容:
import shapeless.{ Generic, HList }, shapeless.ops.product.ToHList
class CaseClassCompanion[C] {
def tupled[P <: Product, R <: HList](p: P)(implicit
gen: Generic.Aux[C, R],
toR: ToHList.Aux[P, R]
): C = gen.from(toR(p))
}
Run Code Online (Sandbox Code Playgroud)
然后:
case class Book(id: Int, isbn: String, name: String)
object Book extends CaseClassCompanion[Book]
case class Author(id: Int, name: String)
object Author extends CaseClassCompanion[Author]
Run Code Online (Sandbox Code Playgroud)
您可以这样使用:
scala> Book.tupled((0, "some ISBN", "some name"))
res0: Book = Book(0,some ISBN,some name)
scala> Author.tupled((0, "some name"))
res1: Author = Author(0,some name)
Run Code Online (Sandbox Code Playgroud)
您可能甚至不想要该CaseClassCompanion部分,因为可以构造一个将元组转换为案例类的通用方法(假设成员类型对齐):
class PartiallyAppliedProductToCc[C] {
def apply[P <: Product, R <: HList](p: P)(implicit
gen: Generic.Aux[C, R],
toR: ToHList.Aux[P, R]
): C = gen.from(toR(p))
}
def productToCc[C]: PartiallyAppliedProductToCc[C] =
new PartiallyAppliedProductToCc[C]
Run Code Online (Sandbox Code Playgroud)
然后:
scala> productToCc[Book]((0, "some ISBN", "some name"))
res2: Book = Book(0,some ISBN,some name)
scala> productToCc[Author]((0, "some name"))
res3: Author = Author(0,some name)
Run Code Online (Sandbox Code Playgroud)
这适用于最多包含22个成员的案例类(因为apply如果有超过22个参数,则无法将伴随对象上的方法扩展为函数).