考虑一个定义两个属性的抽象类
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
并允许我部分构造A
s似乎是合理的
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
。