Slide 1

Slide 1 text

Delightful Delegate Design Braun Márton Szabolcs zsmb.co zsmb13 [email protected]

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

val oneToOne: Pair = 1 to "one"

Slide 4

Slide 4 text

with(user) { println(name) } val oneToOne: Pair = 1 to "one"

Slide 5

Slide 5 text

val reader = BufferedReader(...) reader.use { val line = it.readLine() // ... } with(user) { println(name) } val oneToOne: Pair = 1 to "one"

Slide 6

Slide 6 text

val pi: Double by lazy { val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) } println(pi) println(pi) val reader = BufferedReader(...) reader.use { val line = it.readLine() // ... } with(user) { println(name) } val oneToOne: Pair = 1 to "one"

Slide 7

Slide 7 text

val pi: Double by val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) println(pi) println(pi) lazy } {

Slide 8

Slide 8 text

val pi: Double by val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) println(pi) println(pi) lazy } { https://forums.swift.org/t/pitch-property-delegates/21895

Slide 9

Slide 9 text

val pi: Double by val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) println(pi) println(pi) LazyDelegate( }) {

Slide 10

Slide 10 text

class Constants { private var pi_: Double? = null val pi: Double get() { if (pi_ == null) { val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } pi_ = sqrt(sum * 6.0) } return pi_!! } private var e_: Double? = null val e: Double get() { if (e_ == null) { val sum = (0..20).sumByDouble { 1.0 / (1..it).fold(1, { a, x -> a * x }) } e_ = sum } return e_!! } }

Slide 11

Slide 11 text

class Constants { private var pi_: Double? = null val pi: Double get() { if (pi_ == null) { val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } pi_ = sqrt(sum * 6.0) } return pi_!! } private var e_: Double? = null val e: Double get() { if (e_ == null) { val sum = (0..20).sumByDouble { 1.0 / (1..it).fold(1, { a, x -> a * x }) } e_ = sum } return e_!! } }

Slide 12

Slide 12 text

class Constants { private var pi_: Double? = null val pi: Double get() { if (pi_ == null) { val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } pi_ = sqrt(sum * 6.0) } return pi_!! } private var e_: Double? = null val e: Double get() { if (e_ == null) { val sum = (0..20).sumByDouble { 1.0 / (1..it).fold(1, { a, x -> a * x }) } e_ = sum } return e_!! } }

Slide 13

Slide 13 text

class Constants { private var pi_: Double? = null val pi: Double get() { if (pi_ == null) { val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } pi_ = sqrt(sum * 6.0) } return pi_!! } private var e_: Double? = null val e: Double get() { if (e_ == null) { val sum = (0..20).sumByDouble { 1.0 / (1..it).fold(1, { a, x -> a * x }) } e_ = sum } return e_!! } }

Slide 14

Slide 14 text

val pi: Double by LazyDelegate({ val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) }) println(pi) println(pi)

Slide 15

Slide 15 text

val pi: Double by LazyDelegate({ val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) }) println(pi) println(pi) class LazyDelegate(private val initializer: () -> T) { }

Slide 16

Slide 16 text

val pi: Double by LazyDelegate({ val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) }) println(pi) println(pi) class LazyDelegate(private val initializer: () -> T) { } operator fun getValue(thisRef: Any?, property: KProperty<*>): T { }

Slide 17

Slide 17 text

val pi: Double by LazyDelegate({ val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) }) println(pi) println(pi) class LazyDelegate(private val initializer: () -> T) { } operator fun getValue(thisRef: Any?, property: KProperty<*>): T { } private var value: T? = null

Slide 18

Slide 18 text

class LazyDelegate(private val initializer: () -> T) { } val pi: Double by LazyDelegate({ val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) }) println(pi) println(pi) operator fun getValue(thisRef: Any?, property: KProperty<*>): T { } private var value: T? = null if (value == null) { value = initializer() } return value!!

Slide 19

Slide 19 text

val pi: Double by LazyDelegate({ val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) }) println(pi) // 12597400 ns println(pi) // 72100 ns class LazyDelegate(private val initializer: () -> T) { private var value: T? = null operator fun getValue(thisRef: Any?, property: KProperty<*>): T { if (value == null) { value = initializer() } return value!! } }

Slide 20

Slide 20 text

val pi: Double by LazyDelegate({ val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) }) println(pi) // 12597400 ns println(pi) // 72100 ns class LazyDelegate(private val initializer: () -> T) { private var value: T? = null operator fun getValue(thisRef: Any?, property: KProperty<*>): T { if (value == null) { value = initializer() } return value!! } }

Slide 21

Slide 21 text

val pi: Double by LazyDelegate { val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) } println(pi) // 12597400 ns println(pi) // 72100 ns class LazyDelegate(private val initializer: () -> T) { private var value: T? = null operator fun getValue(thisRef: Any?, property: KProperty<*>): T { if (value == null) { value = initializer() } return value!! } }

Slide 22

Slide 22 text

val pi: Double by lazy { val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) } println(pi) // 12597400 ns println(pi) // 72100 ns class LazyDelegate(private val initializer: () -> T) { private var value: T? = null operator fun getValue(thisRef: Any?, property: KProperty<*>): T { if (value == null) { value = initializer() } return value!! } }

Slide 23

Slide 23 text

val pi: Double by lazy { val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) } println(pi) // 12597400 ns println(pi) // 72100 ns class lazy(private val initializer: () -> T) { private var value: T? = null operator fun getValue(thisRef: Any?, property: KProperty<*>): T { if (value == null) { value = initializer() } return value!! } }

Slide 24

Slide 24 text

val pi: Double by lazy { val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) } println(pi) // 12597400 ns println(pi) // 72100 ns class LazyDelegate(private val initializer: () -> T) { private var value: T? = null operator fun getValue(thisRef: Any?, property: KProperty<*>): T { if (value == null) { value = initializer() } return value!! } }

Slide 25

Slide 25 text

fun lazy(initializer: () -> T) = LazyDelegate(initializer) class LazyDelegate(private val initializer: () -> T) { private var value: T? = null operator fun getValue(thisRef: Any?, property: KProperty<*>): T { if (value == null) { value = initializer() } return value!! } } val pi: Double by lazy { val sum = (1..50_000).sumByDouble { 1.0 / (it * it) } sqrt(sum * 6.0) } println(pi) // 12597400 ns println(pi) // 72100 ns

Slide 26

Slide 26 text

https://github.com/AutSoft/Krate

Slide 27

Slide 27 text

krate interface Krate { val sharedPreferences: SharedPreferences }

Slide 28

Slide 28 text

krate interface Krate { val sharedPreferences: SharedPreferences } abstract class SimpleKrate(context: Context) : Krate { override val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) }

Slide 29

Slide 29 text

krate interface Krate { val sharedPreferences: SharedPreferences } abstract class SimpleKrate(context: Context) : Krate { override val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) } app

Slide 30

Slide 30 text

app krate class MyKrate(context: Context) : SimpleKrate(context) { var onboarded by booleanPref("onboarded") var appOpenCount by intPref("appOpenCount") var username by stringPref("username") } myKrate.onboarded = true myKrate.appOpenCount++ myKrate.username = "t1gg3r" interface Krate { val sharedPreferences: SharedPreferences } abstract class SimpleKrate(context: Context) : Krate { override val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) }

Slide 31

Slide 31 text

app krate interface Krate { val sharedPreferences: SharedPreferences }

Slide 32

Slide 32 text

krate app interface Krate { val sharedPreferences: SharedPreferences }

Slide 33

Slide 33 text

krate app interface Krate { val sharedPreferences: SharedPreferences } class MyKrate(context: Context) : SimpleKrate(context) { }

Slide 34

Slide 34 text

krate app interface Krate { val sharedPreferences: SharedPreferences } class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by ??? }

Slide 35

Slide 35 text

app krate interface Krate { val sharedPreferences: SharedPreferences } class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by ??? } println(myKrate.score) // 0 myKrate.score = 34 println(myKrate.score) // 34

Slide 36

Slide 36 text

app krate interface Krate { val sharedPreferences: SharedPreferences } class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by ??? } println(myKrate.score) // 0 myKrate.score = 34 println(myKrate.score) // 34 class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { }

Slide 37

Slide 37 text

krate app interface Krate { val sharedPreferences: SharedPreferences } class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by ??? } println(myKrate.score) // 0 myKrate.score = 34 println(myKrate.score) // 34 class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { }

Slide 38

Slide 38 text

app krate interface Krate { val sharedPreferences: SharedPreferences } class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { } } class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by ??? } println(myKrate.score) // 0 myKrate.score = 34 println(myKrate.score) // 34

Slide 39

Slide 39 text

app krate interface Krate { val sharedPreferences: SharedPreferences } class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by ??? } println(myKrate.score) // 0 myKrate.score = 34 println(myKrate.score) // 34

Slide 40

Slide 40 text

app krate interface Krate { val sharedPreferences: SharedPreferences } class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by ??? } println(myKrate.score) // 0 myKrate.score = 34 println(myKrate.score) // 34

Slide 41

Slide 41 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by IntDelegate(sharedPreferences, "score") } krate interface Krate { val sharedPreferences: SharedPreferences } class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } } println(myKrate.score) // 0 myKrate.score = 34 println(myKrate.score) // 34

Slide 42

Slide 42 text

app krate interface Krate { val sharedPreferences: SharedPreferences } class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by IntDelegate(sharedPreferences, "score") } fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 43

Slide 43 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate interface Krate { val sharedPreferences: SharedPreferences } class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 44

Slide 44 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate interface Krate { val sharedPreferences: SharedPreferences } class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 45

Slide 45 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate interface Krate { val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 46

Slide 46 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 47

Slide 47 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 48

Slide 48 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 49

Slide 49 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) { operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 50

Slide 50 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) : ReadWriteProperty { operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 51

Slide 51 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) : ReadWriteProperty { override operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } override operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 52

Slide 52 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) : ReadWriteProperty { override operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } override operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 53

Slide 53 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) : ReadWriteProperty { override operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } override operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 54

Slide 54 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) : ReadWriteProperty { override operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } override operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 55

Slide 55 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) : ReadWriteProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } override operator fun setValue(thisRef: Krate, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 56

Slide 56 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) : ReadWriteProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } override operator fun setValue(thisRef: Krate, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 57

Slide 57 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) : ReadWriteProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): Int { return sharedPreferences.getInt(key, 0) } override operator fun setValue(thisRef: Krate, property: KProperty<*>, value: Int) { sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 58

Slide 58 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val sharedPreferences: SharedPreferences, private val key: String ) : ReadWriteProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): Int { return thisRef.sharedPreferences.getInt(key, 0) } override operator fun setValue(thisRef: Krate, property: KProperty<*>, value: Int) { thisRef.sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(sharedPreferences, key) }

Slide 59

Slide 59 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val key: String ) : ReadWriteProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): Int { return thisRef.sharedPreferences.getInt(key, 0) } override operator fun setValue(thisRef: Krate, property: KProperty<*>, value: Int) { thisRef.sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): IntDelegate { return IntDelegate(key) }

Slide 60

Slide 60 text

app class MyKrate(context: Context) : SimpleKrate(context) { var score: Int by intPref("score") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class IntDelegate( private val key: String ) : ReadWriteProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): Int { return thisRef.sharedPreferences.getInt(key, 0) } override operator fun setValue(thisRef: Krate, property: KProperty<*>, value: Int) { thisRef.sharedPreferences.edit().putInt(key, value).apply() } } public fun Krate.intPref(key: String): ReadWriteProperty { return IntDelegate(key) }

Slide 61

Slide 61 text

app krate

Slide 62

Slide 62 text

app krate public interface Krate { public val sharedPreferences: SharedPreferences } class MyKrate(context: Context) : SimpleKrate(context) { var users: List? by ??? } myKrate.users = listOf(User("William"), User("Virginia")) println(myKrate.users)

Slide 63

Slide 63 text

app krate public interface Krate { public val sharedPreferences: SharedPreferences } class MyKrate(context: Context) : SimpleKrate(context) { va users: List? by gsonPref("users") } myKrate.users = listOf(User("William"), User("Virginia")) println(myKrate.users) r

Slide 64

Slide 64 text

app krate public interface Krate { public val sharedPreferences: SharedPreferences } class MyKrate(context: Context) : SimpleKrate(context) { va users: List? by gsonPref("users") } myKrate.users = listOf(User("William"), User("Virginia")) println(myKrate.users) l

Slide 65

Slide 65 text

app myKrate.users = listOf(User("William"), User("Virginia")) println(myKrate.users) class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by gsonPref("users") } krate public interface Krate { public val sharedPreferences: SharedPreferences } internal class GsonDelegate( private val key: String ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): T? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, object : TypeToken() {}.type) } }

Slide 66

Slide 66 text

app krate public interface Krate { public val sharedPreferences: SharedPreferences } class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by gsonPref("users") } internal class GsonDelegate( private val key: String ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): T? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, object : TypeToken() {}.type) } } public fun Krate.gsonPref( key: String ): ReadOnlyProperty { return GsonDelegate(key) }

Slide 67

Slide 67 text

app krate public interface Krate { public val sharedPreferences: SharedPreferences } class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by gsonPref("users") } internal class GsonDelegate( private val key: String ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): Object? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, object : TypeToken() {}.type) } } public fun Krate.gsonPref( key: String ): ReadOnlyProperty { return GsonDelegate(key) }

Slide 68

Slide 68 text

app krate public interface Krate { public val sharedPreferences: SharedPreferences } class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by gsonPref("users") } internal class GsonDelegate( private val key: String ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): T? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, object : TypeToken() {}.type) } } public fun Krate.gsonPref( key: String ): ReadOnlyProperty { return GsonDelegate(key) }

Slide 69

Slide 69 text

app krate public interface Krate { public val sharedPreferences: SharedPreferences } class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by gsonPref("users") } public inline fun Krate.gsonPref( key: String ): ReadOnlyProperty { return GsonDelegate(key) } object : TypeToken() {}.type) ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): T? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, } } internal class GsonDelegate( private val key: String

Slide 70

Slide 70 text

app gsonPref("users") class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by } krate public interface Krate { public val sharedPreferences: SharedPreferences } public inline fun Krate.gsonPref( key: String ): ReadOnlyProperty { return GsonDelegate(key, object : TypeToken() {}.type) } object : TypeToken() {}.type) ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): T? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, } } internal class GsonDelegate( private val key: String

Slide 71

Slide 71 text

app class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by } gsonPref("users") krate public interface Krate { public val sharedPreferences: SharedPreferences } public inline fun Krate.gsonPref( key: String ): ReadOnlyProperty { return GsonDelegate(key, object : TypeToken() {}.type) } ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): T? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, } } , private val type: Type type) internal class GsonDelegate( private val key: String

Slide 72

Slide 72 text

app krate public interface Krate { public val sharedPreferences: SharedPreferences } public inline fun Krate.gsonPref( key: String ): ReadOnlyProperty { return GsonDelegate(key, object : TypeToken() {}.type) } GsonDelegate(key, object : TypeToken() {}.type) class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by } gsonPref("users") ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): T? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, } } , private val type: Type type) internal class GsonDelegate( private val key: String

Slide 73

Slide 73 text

app class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by } GsonDelegate( , object : TypeToken< >() {}.type) "users" gsonPref("users") krate public interface Krate { public val sharedPreferences: SharedPreferences } public inline fun Krate.gsonPref( key: String ): ReadOnlyProperty { return GsonDelegate(key, object : TypeToken() {}.type) } ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): T? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, } } , private val type: Type type) internal class GsonDelegate( private val key: String T

Slide 74

Slide 74 text

app GsonDelegate( , object : TypeToken< >() {}.type) "users" List gsonPref("users") krate public interface Krate { public val sharedPreferences: SharedPreferences } public inline fun Krate.gsonPref( key: String ): ReadOnlyProperty { return GsonDelegate(key, object : TypeToken() {}.type) } class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by } ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): T? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, } } , private val type: Type type) internal class GsonDelegate( private val key: String

Slide 75

Slide 75 text

app gsonPref("users") class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by } krate public interface Krate { public val sharedPreferences: SharedPreferences } public inline fun Krate.gsonPref( key: String ): ReadOnlyProperty { return GsonDelegate(key, object : TypeToken() {}.type) } ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): T? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, } } , private val type: Type type) internal class GsonDelegate( private val key: String

Slide 76

Slide 76 text

app gsonPref("users") krate public interface Krate { public val sharedPreferences: SharedPreferences } public inline fun Krate.gsonPref( key: String ): ReadOnlyProperty { return GsonDelegate(key, object : TypeToken() {}.type) } ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): T? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, } } , private val type: Type type) internal class GsonDelegate( private val key: String class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by }

Slide 77

Slide 77 text

app class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by } gsonPref("users") GsonDelegate(...) krate public interface Krate { public val sharedPreferences: SharedPreferences } public inline fun Krate.gsonPref( key: String ): ReadOnlyProperty { return GsonDelegate(key, object : TypeToken() {}.type) } ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): T? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, } } , private val type: Type type) internal class GsonDelegate( private val key: String

Slide 78

Slide 78 text

app krate public interface Krate { public val sharedPreferences: SharedPreferences } class MyKrate(context: Context) : SimpleKrate(context) { val users: List? by gsonPref("users") } @PublishedApi internal class GsonDelegate( private val key: String, private val type: Type ) : ReadOnlyProperty { override operator fun getValue(thisRef: Krate, property: KProperty<*>): T? { val string = thisRef.sharedPreferences.getString(key, null) return Gson().fromJson(string, type) } } public inline fun Krate.gsonPref( key: String ): ReadOnlyProperty { return GsonDelegate(key, object : TypeToken() {}.type) }

Slide 79

Slide 79 text

https://zsmb.co/maintaining-compatibility-in-kotlin-libraries/

Slide 80

Slide 80 text

Krate* class MyKrate(context: Context) : SimpleKrate(context) { var onboarded var appOpenCount var username } myKrate.onboarded = true myKrate.appOpenCount++ println(myKrate.username) by booleanPref("onboarded" by intPref("appOpenCount" by stringPref("username" ) ) )

Slide 81

Slide 81 text

class MyKrate(context: Context) : SimpleKrate(context) { var onboarded: Boolean by booleanPref("onboarded", defaultValue = false) var appOpenCount: Int by intPref("appOpenCount", defaultValue = 0) var username: String? by stringPref("username") } Krate* myKrate.onboarded = true myKrate.appOpenCount++ println(myKrate.username)

Slide 82

Slide 82 text

class MyKrate(context: Context) : SimpleKrate(context) { // non-nullable, has default value var onboarded: Boolean by booleanPref("onboarded", defaultValue = false) var appOpenCount: Int by intPref("appOpenCount", defaultValue = 0) // nullable, null by default var username: String? by stringPref("username") } Krate* myKrate.onboarded = true myKrate.appOpenCount++ println(myKrate.username)

Slide 83

Slide 83 text

class MyKrate(context: Context) : SimpleKrate(context { // non-nullable, has default value var onboarded: Boolean by booleanPref("onboarded", defaultValue = false) var appOpenCount: Int by intPref("appOpenCount", defaultValue = 0) // nullable, null by default var username: String? by stringPref("username") } Krate* myKrate.onboarded = true myKrate.appOpenCount++ println(myKrate.username) )

Slide 84

Slide 84 text

Krate* myKrate.onboarded = true myKrate.appOpenCount++ println(myKrate.username) class MyKrate(context: Context) : SimpleKrate(context , AppSettings { // non-nullable, has default value override var onboarded: Boolean by booleanPref("onboarded", defaultValue = false) override var appOpenCount: Int by intPref("appOpenCount", defaultValue = 0) // nullable, null by default override var username: String? by stringPref("username") } )

Slide 85

Slide 85 text

class MyKrate @Inject constructor(context: Context) // non-nullable, has default value override var onboarded: Boolean by booleanPref("onboarded", defaultValue = false) override var appOpenCount: Int by intPref("appOpenCount", defaultValue = 0) // nullable, null by default override var username: String? by stringPref("username") } : SimpleKrate(context), AppSetti Krate* myKrate.onboarded = true myKrate.appOpenCount++ println(myKrate.username)

Slide 86

Slide 86 text

class MyKrate @Inject constructor(context: Context) // non-nullable, has default value override var onboarded: Boolean by booleanPref("onboarded", defaultValue = false) override var appOpenCount: Int by intPref("appOpenCount", defaultValue = 0) // nullable, null by default override var username: String? by stringPref("username") } Krate* myKrate.onboarded = true myKrate.appOpenCount++ println(myKrate.username) : SimpleKrate(context), AppSettings {

Slide 87

Slide 87 text

References • Krate  https://github.com/AutSoft/Krate • Delightful Delegate Design  https://blog.autsoft.hu/delightful-delegate-design/ • Further reading  Maintaining Compatibility in Kotlin libraries  https://zsmb.co/maintaining-compatibility-in-kotlin-libraries/  Swift Pitch: Property Delegates  https://forums.swift.org/t/pitch-property-delegates/21895  DSL Design  https://zsmb.co/kotlin-dsl-design-with-village-dsl/  Tips for writing a library  https://www.kotlindevelopment.com/tips-for-writing-a-library-in-kotlin/

Slide 88

Slide 88 text

Questions? zsmb.co zsmb13 [email protected] Photo by Agnieszka Kowalczyk on Unsplash