Consider an abstract class defining two properties
abstract class A {
def a: Int
def b: Int
// real A has additional members
}
which is the base class for various case classes such as
case class Foo(a: Int, b: Int) extends A
case class Bar(a: Int, b: Int) extends A
// and many more
Goal: I would finally like to be able to create instances of the aforementioned case classes in two ways, namely
val b1 = Bar(1, 2)
val b2 = Bar(1) has 2
assert(b1 == b2) // must hold
Approach: It therefore seems reasonable to define a helper class that defines has
and that allows me to partially construct A
s
case class PartialA(f: Int => A) {
def has(b: Int) = f(b)
}
Problem: The current machinery doesn't allow for calls like Bar(1)
because this is actually an invocation of Bar.apply(1)
, that is, of the method apply
as defined by the compiler-generated object Bar
.
It would be great if I could force the compiler to generate the Bar
object as object Bar extends PartialAConstructor
, where
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))
}
However, it doesn't seem to be possible to influence the generation of companion objects of case classes.
Desired properties:
Case classes:
Foo
,Bar
etc. should remain case classes because I would like to use the compiler-generated goodies such as structural equality,copy
and automatically generated extractors."Full" structural equality: Defining the case classes as
case class Bar(a: Int)(val b: Int)
is not an option, because the compiler-generated
equals
method only considers the first list of arguments, and thus the following would hold erroneously:assert(Foo(1)(0) == Foo(1)(10))
As little code repetition as possible: For example, it is of course possible to define a
def Bar(a: Int) = PartialA((b: Int) => Bar(a, b))
but that would have to be done for every case class extending
A
, that, isFoo
,Bar
etc.