Any idea how to get this to work without a cast? ...
# getting-started
m
Any idea how to get this to work without a cast?
Copy code
class Reflect1() {
    val prop1: Reflect2? = null
}

class Reflect2() {
    val prop2: Double? = null
}

fun <T, R> accessProp(item: T, prop: KProperty1<T, R>): R {
    return prop.get(item)
}

class Test() {
    init {
        val r = Reflect1()
        accessProp(r.prop1, Reflect2::prop2)
    }
}
casting the property works but seems like there should be a better way?
Copy code
accessProp(r.prop1, Reflect2::prop2 as KProperty1<Reflect2?, Double?>)
Changing item:T to item: T? helps to see the root of the problem
This is how I got it to work:
Copy code
fun <T, R> accessProp(item: T?, prop: KProperty1<T, R>): R? {
    return item?.let { prop.get(it) }
}
Have to use T? and R?
a
It's usually easier to use lambda types than KProperties, so replace
KProperty1<T, R>
with a lambda that accepts T and returns R
Copy code
fun <T, R> accessProp(item: T, prop: (T) -> R): R {
  return prop(item)
}
next, it can help with generics if you try and break things down into really small pieces and use explicit types
Copy code
val r = Reflect1()
val rProp1: Reflect2? = r.prop1
val prop2Accessor: (Reflect2) -> Double? = Reflect2::prop2
accessProp(rProp1, prop2Accessor)
to me this makes it clearer where the mismatch is.
rProp1
has a nullable type of
Reflect2?
, but the lambda of
Reflect2::prop2
only accepts the non-null
Reflect
So the type
T
in
accessProp()
needs to be nullable,
T?
, but
Reflect2::prop2
only accepts a non-null type. To work around it, you can just use a lambda:
Copy code
val r = Reflect1()
accessProp(r.prop1) { reflect2: Reflect2? -> 
  reflect2?.prop2 
}
demo.kt.cpp
m
lambdas end up being noisy when for cases like this :
Copy code
val key = itemProperty().select(JiraIssue::getKeyProperty)
    val summary = itemProperty().select(JiraIssue::getSummaryProperty)
    val description = itemProperty().select(JiraIssue::getDescriptionProperty)
    val url = itemProperty().select(JiraIssue::getUrlProperty)
    val comments = itemProperty().select(JiraIssue::comments)
or for cases where I'm defining a list of properties
Copy code
val testProperties = listOf (
        ModelMutableProperty("Test Num", Test::num),
        ModelMutableProperty("Title", Test::title),
        ModelMutableProperty("Purpose", Test::purpose),
        ModelMutableProperty("State", Test::attractionState),
        ModelMutableProperty("Mode", Test::mode),
        ModelMutableProperty("Material", Test::material)
)
Either way is much better than the JavaFX way of using strings so you only get errors at run time....I mean what are they going for? Python???
Copy code
Bindings.select<ObservableList<JiraComment>>(itemProperty(), "comments")
A lambda isn't too bad
Copy code
val key = itemProperty().select{ it?.keyProperty }