首页 > 解决方案 > Kotlin 在抽象类的非抽象函数中访问抽象函数

问题描述

我有一门课,基本上是这样的:

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实现依赖于,但不能在任何不提供反正的类中调用此实现。reverseinvokeinvoke

最简单的解决方案是reverse在每个类中复制代码,但我宁愿没有代码重复。

所以我的问题是,究竟什么是做我想做的事的优雅方式:提供一个定义明确的行为(reverse),它使用尚未定义的行为(),invoke但在调用时将 100% 定义reverse

标签: objectkotlininheritanceabstract-class

解决方案


问题是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
            }
        }
    }

推荐阅读