Search code examples
kotlindelegatesextension-methodskotlin-logging

Kotlin: Delegate override function how to make work with lambda and function parens


I am trying to override the error() method of kotlin-logging.

The following code is close to what I want, but I don’t understand a few things (I’m new to Kotlin).

Example code:

import mu.KLogger
import mu.KotlinLogging

open class BgrLogging(
    private val delegate: KLogger
) : KLogger by delegate {
    override fun error(msg: () -> Any?) {
        delegate.error("$msg xxxx")
    }
}

fun KLogger.toBgrLogging() = BgrLogging(this)

private val logger = KotlinLogging.logger {}.toBgrLogging()

I would like to be able to call my overridden error() method like so:

logger.error("should override error")
// Output: should override error

… unfortunately, this appears to skip my override and calls the original error() in kotlin-logging.

If I use a lambda:

logger.error{ "should override error" }
// Output: () -> kotlin.Any? xxxx

It calls my override (yay!), but the output is not what I want.

Observation

When I call kotlin-logging directly (no overrides), both of these seem to work as I would expect:

logger.error("foo1")
logger.error{ "foo1" }

It outputs the string as it was passed.

Question

Is it possible to get both logger.error("xxxx") and logger.error{ "xxxx" } to call my overridden function? I’d like both invocations to output the actual string, and not () -> kotlin.Any?.

Java 17
Kotlin Compiler Version: 1.6.10
kotlin-logging 1.5.4

Solution

  • logger.error("should override error")
    

    does not call your overridden error because it has the signature (String) -> Unit whereas you only override the error with signature (() -> Any?) -> Unit. In Kotlin's model, overloaded functions are completely separate from one another.

    If you want to override error when called on strings you will have to override that method as well.