考虑一个定义两个属性的抽象类
abstract class A {
def a: Int
def b: Int
// real A has additional members
}
这是各种案例类的基类,例如
case class Foo(a: Int, b: Int) extends A
case class Bar(a: Int, b: Int) extends A
// and many more
目标:我最终希望能够以两种方式创建上述案例类的实例,即
val b1 = Bar(1, 2)
val b2 = Bar(1) has 2
assert(b1 == b2) // must hold
方法:因此定义一个帮助类来定义has并允许我部分构造As似乎是合理的
case class PartialA(f: Int => A) {
def has(b: Int) = f(b)
}
问题:当前的机器不允许像Bar(1)这样的调用,因为这实际上是对 的调用Bar.apply(1),即apply由编译器生成的对象定义的方法的调用Bar。
如果我可以强制编译器将Bar对象object Bar extends PartialAConstructor生成为
abstract class PartialAConstructor{
def apply(a: Int, b: Int): A // abstract, created when the compiler creates
// object Bar
def apply(a: Int) = PartialA((b: Int) => apply(a, b))
}
但是,似乎不可能影响案例类的伴随对象的生成。
所需属性:
案例类:
Foo等Bar应该保留案例类,因为我想使用编译器生成的好东西,例如结构相等copy和自动生成的提取器。“完全”结构平等:将案例类定义为
case class Bar(a: Int)(val b: Int)不是一个选项,因为编译器生成的
equals方法只考虑第一个参数列表,因此以下内容将错误地成立:assert(Foo(1)(0) == Foo(1)(10))尽可能少的代码重复:例如,当然可以定义一个
def Bar(a: Int) = PartialA((b: Int) => Bar(a, b))但是对于扩展的每个案例类都必须这样做
A,即 isFoo等Bar。