Skip to content

Kotlin compiler plugin that allows class delegation to be dynamic like property delegations

License

Notifications You must be signed in to change notification settings

elide-tools/kotlin-dynamic-delegation

 
 

Repository files navigation

kotlin-dynamic-delegation

Kotlin compiler plugin that allows class delegation to be dynamic like property delegations.

Features

Dynamic Delegations

The plugin provides:

public fun <R> dynamicDelegation(value: () -> R): R =
    throw NotImplementedError("Implemented as intrinsic")

This function is implemented by the compiler. Here is an example.

Suppose this is your existing code and is published to the public:

interface CommandManager {
    val commands: List<Command>
    fun register(command: Command)

    companion object : CommandManager {
        // implement CommandManager
    }
}

Suppose then you realized the CommandManager instance should not be static (statically initialized or singleton). You changed the CommandManager to this because you cannot remove code that have been published to the public:

interface CommandManager {
    val commands: List<Command>
    fun register(command: Command)

    companion object : CommandManager {
        private val instance by lazy { CommandManagerImpl() }

        // You must manually delegate all calls to instance
        override val commands: List<Command> get() = instance.commands
        override fun register(command: Command): Unit = instance.register(command)
    }
}

Now with Kotlin Dynamic Delegation, you can do instead:

interface CommandManager {
    val commands: List<Command>
    fun register(command: Command)

    companion object : CommandManager by (dynamicDelegation(Companion::instance)) {
        private val instance by lazy { CommandManagerImpl() }

        // All delegates will be generated automatically
    }
}

Alternatively, it's also possible to do this:

interface CommandManager {
    val commands: List<Command>
    fun register(command: Command)

    companion object : CommandManager by (dynamicDelegation { getCommandManagerImpl() }) {
        // All delegates will be generated automatically
    }
}

private fun getCommandManagerImpl(): CommandManager {
    // This is called to get actual CommandManager instance when a member inside CommandManager.Companion is called.

    if (!someChecks()) {
        error("It's not the time to call CommandManager!")
    }
    if (someOtherChecks()) {
        currentInstance = CommandManagerImpl() // Possible to update delegated instance
    }
    return currentInstance
}
private var currentInstance: CommandManager = CommandManagerImpl()

Using Lazy In Functions

Functions can also be 'lazy' by making a value lazy and persistent.

override fun toString(): String = persistent { this.joinToString() } // initialize lazily once and use afterwards.

is the same as

private val toStringTemp by lazy { this.joinToString() }
override fun toString(): String = toStringTemp

Using the plugin

build.gradle.kts

plugins {
    id("me.him188.kotlin-dynamic-delegation") version "VERSION"
}

You also need to add a 'compileOnly' dependency 'me.him188:kotlin-dynamic-delegation-runtime':

For JVM projects:

dependencies {
    implementation("me.him188:kotlin-dynamic-delegation:VERSION")
}

For MPP, adding to commonMain would automatically add for all targets:

kotlin.sourceSets {
    commonMain {
        dependencies {
            implementation("me.him188:kotlin-dynamic-delegation:VERSION")
        }
    }
}

See VERSION from releases

Installing IntelliJ IDEA plugin

IDEA plugin can help to edit code and to report errors before compiling the code. By seeing the type cast hint(see picture below), you will know, without compiling, that your code with dynamic delegations will work.

Plugin Marketplace Page: https://plugins.jetbrains.com/plugin/18219-kotlin-dynamic-delegation

About

Kotlin compiler plugin that allows class delegation to be dynamic like property delegations

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Kotlin 100.0%