This is a simplified version of what I'm actually ...
# getting-started
j
This is a simplified version of what I'm actually doing, so please bear with me. I'm trying to do something with property delegates. I have a class which implements
List
via delegation. I set up a property delegate function to add to the list whenever a property is defined in the class. This is just a way for me to iterate through properties of a class. The class itself uses a map as the "backing field" data structure (for lack of a better term)
Copy code
class ListItem<T>(
    val itemName: String,
    val getValue: () -> T,
)

class MyList(private val list: MutableList<ListItem<*>>) : List<ListItem<*>> by list {
    constructor() : this(mutableListOf())

    private val map: Map<String, Any> = mapOf(
        "item1" to 1,
        "item2" to "2",
    )

    val item1: Int by listItem()
    val item2: String by listItem()

    private fun <T> listItem() = PropertyDelegateProvider { thisRef: MyList, prop ->
        val item = ListItem(prop.name) {
            thisRef.map[prop.name]!! as T // Unchecked cast
        }
        thisRef.list.add(item)
        ReadOnlyProperty { _: MyList, _ -> item }
    }
}
With this, I should be able to do
Copy code
val myList = MyList()
myList.forEach { println("${it.name} ${it.getValue()}") }
but also this
Copy code
myList.item1
myList.item2
I'm getting an unhelpful error message when declaring the properties in the class body:
Copy code
Property delegate must have a 'getValue(MyList, KProperty*>)' method. None of the following functions are suitable.
- getValue(MyList, KProperty<*>) defined in kotlin.properties.ReadOnlyProperty
Any idea what's going on?
seems that doing this works
Copy code
val item1 by listItem<Int>()
val item2 by listItem<String>()
Not sure why though
Oh. I think it's because specifying the type the first way puts it as the type parameter of the actual
ReadOnlyProperty
. I needed to specify it as the type parameter for the function itself.
a
I'm not sure I 100% understand your example, but replacing
Copy code
ReadOnlyProperty { _: MyList, _ -> item }
with
Copy code
ReadOnlyProperty { _: MyList, _ -> item.getValue() }
makes the red go away
j
Yeah that makes sense. The function returns
ReadOnlyProperty<ListItem<T>>
but by specifying the type at the property declaration, I was asking for
ReadOnlyProperty<T>
m
I think your casting will be problematic due to type erasure.