upon first access) ×Observable (listeners get notified about changes) ×Storing in a map, not in separate field each ×<Whatever I want property semantics>
File) ×You offer a limited API, using 98% of the existing code ×You want to hide the implementation from calling code, so clients cannot cast to the superclass
fun getValue(thisRef: R, prop: KProperty<*>): T // For var operator fun getValue(thisRef: R, prop: KProperty<*>): T operator fun setValue(thisRef: R, prop: KProperty<*>, value: T) Property metadata Property owner
interface ReadOnlyProperty<in R, out T> { operator fun getValue(thisRef: R, prop: KProperty<*>): T } // For var interface ReadWriteProperty<in R, T> { operator fun getValue(thisRef: R, prop: KProperty<*>): T operator fun setValue(thisRef: R, prop: KProperty<*>, value: T) }
} class NameVar: ReadWriteProperty<Person, String> { override fun getValue(…): { … } override fun setValue(thisRef: Person, prop: KProperty<*>, value: String) { println("$value has been assigned to '${prop.name} in $thisRef.'") } }
private var lastName: TextView by Delegates.notNull() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) firstName = findViewById(R.id.first_name) as TextView lastName = findViewById(R.id.last_name) as TextView } }
bindView(R.id.first_name) private val lastName by bindView<TextView>(R.id.last_name) } fun <V : View> Activity.bindView(id: Int): V = lazy(LazyThreadSafetyMode.NONE) { findViewById(id) as V } Say `no` to annotation processing
for view vals. It will still point to the old view instance after fragment view recreation. pic.twitter.com/gmjQwy0wjc — Chris Banes (@chrisbanes) August 14, 2017
return object : ReadOnlyProperty<Activity, V> { private var value: Any? = EMPTY override fun getValue(thisRef: Activity, property: KProperty<*>): V { if (value == EMPTY) { value = thisRef.findViewById(id) as V? ?: throw IllegalStateException() } return value as V } } }
200L set(value) { field = value invalidate() } var centerY: Long = 300L set(value) { field = value invalidate() } var radius: Int = 150 set(value) { field = value invalidate() } }
var centerY by bindValue(300L) var radius by bindValue(150) } fun <T> View.bindValue(value: T) = Delegates.observable(value) { _, _, _ -> invalidate() }
Delegated Properties (since 1.1) ×Build similar type-safe APIs on top of other unsafe APIs: Bundle, Intent, Cursor ×Bind resources: dimen, color, anim, drawable ×Take a look at DI frameworks without annotation processing: KOIN, injekt etc