Reputation: 1767
I have a class that is basically this:
abstract class BaseContinuousSingleObjectiveFitnessFunction {
// Invoke should compute some function, like f(x) = x^2 + 3x + 5
abstract fun invoke(x: List<Double>): Double
// This is supposed to return an object deriving this one where
// invoke actually returns 1/(1+f(x)), essentially reversing the function.
fun reverse(): BaseContinuousSingleObjectiveFitnessFunction =
object: BaseContinuousSingleObjectiveFitnessFunction() {
override operator fun invoke(x: List<Double>): Double {
var denominator = 1.0 + super.invoke(x)
if (denominator.absoluteValue < Double.MIN_VALUE * 10)
denominator += denominator.sign * Double.MIN_VALUE * 10
return 1.0 / denominator
}
}
}
Problem is that invoke
is abstract so the compiler complains that Abstract member cannot be accessed directly.
which is true.
However any class deriving my class will obviously be forced to implement invoke
so conceptually there should no problem with calling reverse
in those classes but having the implementation in this base class. The implementation of reverse
while strictly speaking is dependent on invoke
, this implementation can not be called in any class that does not also provide an invoke
anyway.
The simplest solution is to duplicate the code for reverse
in every class but i'd rather not have code duplication.
So my question is what exactly is an elegant way of doing what I want: providing a well-defined behaviour (reverse
) that uses behaviour not defined yet (invoke
) but that will 100% be defined at the time when reverse
is called?
Upvotes: 0
Views: 522
Reputation: 20157
The problem is that super.invoke(x)
is trying to call the super method of the object that derives directly from BaseContinuousSingleObjectiveFitnessFunction
. Since there's no super implementation, you get the error. You probably want to hold a reference to the original function:
fun reverse(): BaseContinuousSingleObjectiveFitnessFunction {
val originalFunction = this
return object: BaseContinuousSingleObjectiveFitnessFunction() {
override operator fun invoke(x: List<Double>): Double {
var denominator = 1.0 + originalFunction.invoke(x)
if (denominator.absoluteValue < Double.MIN_VALUE * 10)
denominator += denominator.sign * Double.MIN_VALUE * 10
return 1.0 / denominator
}
}
}
Upvotes: 2