定义要在scala中按案例类扩展的特征
发布时间:2020-12-16 08:50:21 所属栏目:安全 来源:网络整理
导读:我有一些case类,它的伴随对象中定义了一个方法元组.从下面的代码对象中可以看出,它只是代码重复. case class Book(id: Int,isbn: String,name: String)object Book { def tupled = (Book.apply _).tupled // Duplication}case class Author(id: Int,name: St
我有一些case类,它的伴随对象中定义了一个方法元组.从下面的代码对象中可以看出,它只是代码重复.
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 } 从另一个问题(can a scala self type enforce a case class type),似乎我们不能强制将特征的自我类型作为案例类. 有没有办法定义一个可以应用如下的特征(比如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 { } 解决方法
因为Scala中的FunctionN类型之间没有关系,所以如果没有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)) } 然后: case class Book(id: Int,name: String) object Book extends CaseClassCompanion[Book] case class Author(id: Int,name: String) object Author extends CaseClassCompanion[Author] 您可以这样使用: 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) 您甚至可能不想要CaseClassCompanion部分,因为可以构造一个将元组转换为案例类的通用方法(假设成员类型对齐): class PartiallyAppliedProductToCc[C] { def apply[P <: Product,R] ): C = gen.from(toR(p)) } def productToCc[C]: PartiallyAppliedProductToCc[C] = new PartiallyAppliedProductToCc[C] 然后: scala> productToCc[Book]((0,"some name")) res2: Book = Book(0,some name) scala> productToCc[Author]((0,"some name")) res3: Author = Author(0,some name) 这适用于最多包含22个成员的案例类(因为如果有超过22个参数,则无法将伴随对象上的apply方法扩展为函数). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |