Kotlin доступ к абстрактной функции в неабстрактной функции в абстрактном классе - PullRequest
0 голосов
/ 12 марта 2020

У меня есть класс, который в основном такой:

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
                }
            }
}

Проблема в том, что invoke является абстрактным, поэтому компилятор жалуется, что Abstract member cannot be accessed directly., что верно.

Однако любой класс, производный от моего класса, очевидно, будет вынужден реализовать invoke, поэтому концептуально не должно быть проблем с вызовом reverse в этих классах, но с реализацией в этом базовом классе. Реализация reverse, в то время как строго говоря зависит от invoke, эта реализация не может быть вызвана ни в одном классе, который также не обеспечивает invoke.

Простейший Решение состоит в том, чтобы дублировать код для reverse в каждом классе, но я бы предпочел не иметь дублирования кода.

Поэтому мой вопрос заключается в том, что именно представляет собой элегантный способ сделать то, что я хочу: обеспечить четко определенное поведение (reverse), которое использует поведение, еще не определенное (invoke), но это будет на 100% определен в тот момент, когда вызывается reverse?

1 Ответ

2 голосов
/ 12 марта 2020

Проблема в том, что super.invoke(x) пытается вызвать супер-метод объекта, который происходит непосредственно от BaseContinuousSingleObjectiveFitnessFunction. Поскольку нет супер реализации, вы получите ошибку. Возможно, вы хотите сохранить ссылку на исходную функцию:

    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
            }
        }
    }
...