[SOLVED][Request] Put extension delegate property in receiver scope

I think that Kotlin could benefit from putting the delegate inside of the receiver scope when extending a property.

How possible would it be to put the delegate declaration inside the scope of the receiver?

For this example, say we cannot change Player and the developer gave us some data, but we know nothing about the data. It would allow us to do something like this

import kotlin.reflect.KProperty

data class Player(val useraname: String, val playerId: Int, var someData: Int)

fun Int.getBits(startBit: Int, endBit: Int): Int =
    TODO("Get a value representing all bits in this inclusively between startBit and endBit")

fun Int.setBits(startBit: Int, endBit: Int, value: Int): Int =
    TODO("Return this int with all bits from startBit to endBit replaced with value's bits")

class PlayerData(val player: Player, val dataStartBit: Int, val dataEndBit: Int) {

    operator fun getValue(ref: Any?, prop: KProperty<*>): Int = player.someData.getBits(dataStartBit, dataEndBit)

    operator fun setValue(ref: Any?, prop: KProperty<*>, value: Int) {
        player.someData = player.someData.setBits(dataStartBit, dataEndBit, value)
    }
}

// this is the instance of the player
var Player.health by PlayerData(this, 0, 7)
var Player.mana by PlayerData(this, 8, 15)
var Player.stamina by PlayerData(this, 16, 23)

I think this is an improvement in quality of life over something like the current “solution” to this problem which is more long winded than the proposed alternative while increasing code re-usability and decreasing copy-paste.

var Player.health: Int
    get() = someData.getBits(0, 7)
    set(value) { someData.setBits(0, 7, value) }

var Player.mana: Int
    get() = someData.getBits(8, 15)
    set(value) { someData.setBits(8, 15, value) }

var Player.stamina: Int
    get() = someData.getBits(16, 23)
    set(value) { someData.setBits(16, 23, value) }
`

Is this what you want to achieve?

class PlayerData(val dataStartBit: Int, val dataEndBit: Int) {

    operator fun getValue(ref: Player, prop: KProperty<*>): Int =
        ref.someData.getBits(dataStartBit, dataEndBit)

    operator fun setValue(ref: Player, prop: KProperty<*>, value: Int) {
        ref.someData = ref.someData.setBits(dataStartBit, dataEndBit, value)
    }
}

var Player.health by PlayerData(0, 7)
var Player.mana by PlayerData(8, 15)
var Player.stamina by PlayerData(16, 23)
1 Like

This is actually exactly what I want to achieve. I had no idea what ref actually did and assumed it was just arbitrarily there.

Thank you!