This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
inline fun <reified T> Iterable<*>.filterIsInstance() = filter { it is T }
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val set = setOf("1984", 2, 3, "Brave new world", 11)
|
||||
println(set.filterIsInstance<Int>())
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.baeldung.kotlin.delegates
|
||||
|
||||
val data = arrayOf<MutableMap<String, Any?>>(
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.kotlin.delegates
|
||||
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class DatabaseDelegate<in R, T>(private val field: String, private val id: Int) : ReadWriteProperty<R, T> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.baeldung.kotlin.delegates
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.concurrent.withLock
|
||||
|
||||
interface Producer {
|
||||
|
||||
fun produce(): String
|
||||
}
|
||||
|
||||
class ProducerImpl : Producer {
|
||||
|
||||
override fun produce() = "ProducerImpl"
|
||||
}
|
||||
|
||||
class EnhancedProducer(private val delegate: Producer) : Producer by delegate {
|
||||
|
||||
override fun produce() = "${delegate.produce()} and EnhancedProducer"
|
||||
}
|
||||
|
||||
interface MessageService {
|
||||
|
||||
fun processMessage(message: String): String
|
||||
}
|
||||
|
||||
class MessageServiceImpl : MessageService {
|
||||
override fun processMessage(message: String): String {
|
||||
return "MessageServiceImpl: $message"
|
||||
}
|
||||
}
|
||||
|
||||
interface UserService {
|
||||
|
||||
fun processUser(userId: String): String
|
||||
}
|
||||
|
||||
class UserServiceImpl : UserService {
|
||||
|
||||
override fun processUser(userId: String): String {
|
||||
return "UserServiceImpl: $userId"
|
||||
}
|
||||
}
|
||||
|
||||
class CompositeService : UserService by UserServiceImpl(), MessageService by MessageServiceImpl()
|
||||
|
||||
interface Service {
|
||||
|
||||
val seed: Int
|
||||
|
||||
fun serve(action: (Int) -> Unit)
|
||||
}
|
||||
|
||||
class ServiceImpl : Service {
|
||||
|
||||
override val seed = 1
|
||||
|
||||
override fun serve(action: (Int) -> Unit) {
|
||||
action(seed)
|
||||
}
|
||||
}
|
||||
|
||||
class ServiceDecorator : Service by ServiceImpl() {
|
||||
override val seed = 2
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.baeldung.kotlin
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class GenericsTest {
|
||||
|
||||
@Test
|
||||
fun givenParametrizeClass_whenInitializeItWithSpecificType_thenShouldBeParameterized() {
|
||||
//given
|
||||
val parameterizedClass = ParameterizedClass<String>("string-value")
|
||||
|
||||
//when
|
||||
val res = parameterizedClass.getValue()
|
||||
|
||||
//then
|
||||
assertTrue(res is String)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenParametrizeClass_whenInitializeIt_thenShouldBeParameterizedByInferredType() {
|
||||
//given
|
||||
val parameterizedClass = ParameterizedClass("string-value")
|
||||
|
||||
//when
|
||||
val res = parameterizedClass.getValue()
|
||||
|
||||
//then
|
||||
assertTrue(res is String)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenParameterizedProducerByOutKeyword_whenGetValue_thenCanAssignItToSuperType() {
|
||||
//given
|
||||
val parameterizedProducer = ParameterizedProducer("string")
|
||||
|
||||
//when
|
||||
val ref: ParameterizedProducer<Any> = parameterizedProducer
|
||||
|
||||
//then
|
||||
assertTrue(ref is ParameterizedProducer<Any>)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenParameterizedConsumerByInKeyword_whenGetValue_thenCanAssignItToSubType() {
|
||||
//given
|
||||
val parameterizedConsumer = ParameterizedConsumer<Number>()
|
||||
|
||||
//when
|
||||
val ref: ParameterizedConsumer<Double> = parameterizedConsumer
|
||||
|
||||
//then
|
||||
assertTrue(ref is ParameterizedConsumer<Double>)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenTypeProjections_whenOperateOnTwoList_thenCanAcceptListOfSubtypes() {
|
||||
//given
|
||||
val ints: Array<Int> = arrayOf(1, 2, 3)
|
||||
val any: Array<Any?> = arrayOfNulls(3)
|
||||
|
||||
//when
|
||||
copy(ints, any)
|
||||
|
||||
//then
|
||||
assertEquals(any[0], 1)
|
||||
assertEquals(any[1], 2)
|
||||
assertEquals(any[2], 3)
|
||||
|
||||
}
|
||||
|
||||
fun copy(from: Array<out Any>, to: Array<Any?>) {
|
||||
assert(from.size == to.size)
|
||||
for (i in from.indices)
|
||||
to[i] = from[i]
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenTypeProjection_whenHaveArrayOfIn_thenShouldAddElementsOfSubtypesToIt() {
|
||||
//given
|
||||
val objects: Array<Any?> = arrayOfNulls(1)
|
||||
|
||||
//when
|
||||
fill(objects, 1)
|
||||
|
||||
//then
|
||||
assertEquals(objects[0], 1)
|
||||
}
|
||||
|
||||
fun fill(dest: Array<in Int>, value: Int) {
|
||||
dest[0] = value
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenStartProjection_whenPassAnyType_thenCompile() {
|
||||
//given
|
||||
val array = arrayOf(1,2,3)
|
||||
|
||||
//then
|
||||
printArray(array)
|
||||
|
||||
}
|
||||
|
||||
fun printArray(array: Array<*>) {
|
||||
array.forEach { println(it) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenFunctionWithDefinedGenericConstraints_whenCallWithProperType_thenCompile(){
|
||||
//given
|
||||
val listOfInts = listOf(5,2,3,4,1)
|
||||
|
||||
//when
|
||||
val sorted = sort(listOfInts)
|
||||
|
||||
//then
|
||||
assertEquals(sorted, listOf(1,2,3,4,5))
|
||||
}
|
||||
|
||||
fun <T: Comparable<T>> sort(list: List<T>): List<T>{
|
||||
return list.sorted()
|
||||
}
|
||||
|
||||
class ParameterizedClass<A>(private val value: A) {
|
||||
|
||||
fun getValue(): A {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class ParameterizedProducer<out T>(private val value: T) {
|
||||
fun get(): T {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class ParameterizedConsumer<in T> {
|
||||
fun toString(value: T): String {
|
||||
return value.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.kotlin.delegates
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
|
||||
class InterfaceDelegationTest {
|
||||
|
||||
@Test
|
||||
fun `when delegated implementation is used then it works as expected`() {
|
||||
val producer = EnhancedProducer(ProducerImpl())
|
||||
assertThat(producer.produce()).isEqualTo("ProducerImpl and EnhancedProducer")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when composite delegation is used then it works as expected`() {
|
||||
val service = CompositeService()
|
||||
assertThat(service.processMessage("message")).isEqualTo("MessageServiceImpl: message")
|
||||
assertThat(service.processUser("user")).isEqualTo("UserServiceImpl: user")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when decoration is used then delegate knows nothing about it`() {
|
||||
val service = ServiceDecorator()
|
||||
service.serve {
|
||||
assertThat(it).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user