Ive been looking hard for quite some time for this magic feature and have not found it. Every seemingly promising approach requires at least two nearly identical classes, if not more. I have found (and implemented) several approaches that achieve this by some form of code generation, but it ‘feels dirty’ –
Essentially the basic problem comes down to the fact that class delegation requires both an interface and an instance (concrete) class, and/or that field delegation require a ‘by delegate’ for each field individually.
Since class level delegation requires an Interface to derive from but a concrete class to delegate to, there is no way using native language features to avoid duplicating every single field somewhere – either field by field using field delegation, or by creating a full concrete class (field by field explicitly).
There is simply no way define a class and its properties once and then say “I want w new class just like THIS one but with all properties “var”” or “I want a concrete class just like this interface with all properties”.
Even delegating properties by a generic ‘Map’ doesnt solve this as you must explicitly enumerate each individual property with a ‘by map’ – you cant do
class derived : base by mapOf()
or any other way to achive the same.
The best I have found is to create a base Interface, then using various tricks like Proxy or code generation (source or bytecode via asm/bytebuddy) create variants of the base class which can then be used for delegation.
For example I have working code that can do this:
interface Base { val a : String, val b: Int … }
val dervied = configure<Base>() { from( "config file" ) }
This doesnt turn a val into a var or visa versa – but does allow one to construct a purely val object from a purely val interface with data taken from elsewhere at runtime.
To turn a val to var or visa versa requires something similar but at compile time instead. There are some frameworks that can do something fairly close which I am modeling a POC on … something like
@CloneVal( package = "val.package" )
data class VarClass( var a : String , var b : Int ... )
->>
which would produce a new class similar to “VarClass” but using val instead.
Its a bit more work to make them both derive from the same interface …
And yet more work to make an IDE like Eclipse or IntelliJ play nicely.