I'm trying to implement/override a function with an empty input argument by using partial function. It is best explained by this non-working minimal example:
trait T
trait TFactory {
def build(): T
}
class A(someParameter: Int) extends T
object A extends TFactory {
def build(someParameter: Int)(): T = new A(someParameter)
}
The compiler complains: object creation impossible, since method build in trait TFactory of type ()T is not defined
, which makes sense, since the type of build is (Int)()T
. My next idea was to make the type of build
explicitly to a function taking an empty argument and returning a T
, i.e.:
trait T
trait TFactory {
def build: () => T // what about empty parenthesis after build?
}
class A(someParameter: Int) extends T
object A extends TFactory {
def build(someParameter: Int): (() => T) = (() => new A(someParameter))
}
Now it is obvious that the type of build
is () => T
. To my surprise the compiler now complains about object creation impossible, since method build in trait TFactory of type => () => T is not defined
(note the type suddenly starts with a =>
). Desperately adding empty parenthesis at the end of the function definition(s) does not help either.
How can I convince my compiler that these types actually are the same?
Clarification:
My primary goal is to achieve a parameter-free initialization of T
without the need of a factory for factories. Example:
val t = A(33).build() // if this is possible, I though it might be possible to have:
val t = A.build(33)()
Conclusion:
I think it is just not possible, because the abstract function simply determines how many argument blocks the build
function must take. In other words: You cannot by implemented an abstract function by a function, whose partial application happens to have the same signature as the function you are trying to implement.
I not exactly sure what you want to achieve. Let's say your TFactory
was given as in your first example:
trait T
trait TFactory {
def build(): T
}
Then the build
method obviously cannot take any parameter. If you want to configure your factory, you can have a factory-factory:
class A(x: Int) extends T
object A {
def apply(x: Int): TFactory = new TFactory {
def build() = new A(x)
}
}
val factory = A(33)
val t = factory.build()
If you define TFactory
simply to be a function from ()
to T
, you can use currying
type TFactory = () => T
object A {
def apply(x: Int)(): T = new A(x)
}
val factory: TFactory = A(33) _
val t = factory()