From 8137c203495d67a3afd1e2f902e39ff9c7310b9a Mon Sep 17 00:00:00 2001 From: Graham Cox Date: Wed, 2 Aug 2017 18:42:13 +0100 Subject: [PATCH] Delegated Properties in Kotlin (#2357) This produces a fake Database representation - working in terms of hardcoded data, a Delegate that loads values from this fake Database, and then a class with fields delegated to the fake database. --- .../com/baeldung/kotlin/delegates/Database.kt | 35 +++++++++++++++++++ .../kotlin/delegates/DatabaseDelegate.kt | 13 +++++++ .../com/baeldung/kotlin/delegates/User.kt | 6 ++++ .../kotlin/delegates/DatabaseDelegatesTest.kt | 26 ++++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/Database.kt create mode 100644 kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegate.kt create mode 100644 kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/User.kt create mode 100644 kotlin/src/test/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegatesTest.kt diff --git a/kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/Database.kt b/kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/Database.kt new file mode 100644 index 0000000000..9ea9f027fc --- /dev/null +++ b/kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/Database.kt @@ -0,0 +1,35 @@ +package com.baeldung.kotlin.delegates + +val data = arrayOf>( + mutableMapOf( + "id" to 1, + "name" to "George", + "age" to 4 + ), + mutableMapOf( + "id" to 2, + "name" to "Charlotte", + "age" to 2 + ) +) + +class NoRecordFoundException(id: Int) : Exception("No record found for id $id") { + init { + println("No record found for ID $id") + } +} + +fun queryForValue(field: String, id: Int): Any { + println("Loading record $id from the fake database") + val value = data.firstOrNull { it["id"] == id } + ?.get(field) ?: throw NoRecordFoundException(id) + println("Loaded value $value for field $field of record $id") + return value +} + +fun update(field: String, id: Int, value: Any?) { + println("Updating field $field of record $id to value $value in the fake database") + data.firstOrNull { it["id"] == id } + ?.put(field, value) + ?: throw NoRecordFoundException(id) +} diff --git a/kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegate.kt b/kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegate.kt new file mode 100644 index 0000000000..c1c0f8823c --- /dev/null +++ b/kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegate.kt @@ -0,0 +1,13 @@ +package com.baeldung.kotlin.delegates + +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +class DatabaseDelegate(private val field: String, private val id: Int) : ReadWriteProperty { + override fun getValue(thisRef: R, property: KProperty<*>): T = + queryForValue(field, id) as T + + override fun setValue(thisRef: R, property: KProperty<*>, value: T) { + update(field, id, value) + } +} diff --git a/kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/User.kt b/kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/User.kt new file mode 100644 index 0000000000..7788305ea1 --- /dev/null +++ b/kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/User.kt @@ -0,0 +1,6 @@ +package com.baeldung.kotlin.delegates + +class User(val id: Int) { + var name: String by DatabaseDelegate("name", id) + var age: Int by DatabaseDelegate("age", id) +} diff --git a/kotlin/src/test/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegatesTest.kt b/kotlin/src/test/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegatesTest.kt new file mode 100644 index 0000000000..fc50730dfa --- /dev/null +++ b/kotlin/src/test/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegatesTest.kt @@ -0,0 +1,26 @@ +package com.baeldung.kotlin.delegates + +import org.junit.Test +import kotlin.test.assertEquals + +class DatabaseDelegatesTest { + @Test + fun testGetKnownFields() { + val user = User(1) + assertEquals("George", user.name) + assertEquals(4, user.age) + } + + @Test + fun testSetKnownFields() { + val user = User(2) + user.age = 3 + assertEquals(3, user.age) + } + + @Test(expected = NoRecordFoundException::class) + fun testGetKnownField() { + val user = User(3) + user.name + } +}