diff --git a/core-kotlin-modules/core-kotlin-11/README.md b/core-kotlin-modules/core-kotlin-11/README.md index 01d4be992..85dd5b68e 100644 --- a/core-kotlin-modules/core-kotlin-11/README.md +++ b/core-kotlin-modules/core-kotlin-11/README.md @@ -1,2 +1,2 @@ ### Relevant Articles -- [Convert a Data Class to ByteBuffer in Kotlin](https://www.baeldung.com/kotlin/convert-data-class-to-bytebuffer) + diff --git a/core-kotlin-modules/core-kotlin-12/README.md b/core-kotlin-modules/core-kotlin-12/README.md new file mode 100644 index 000000000..8b366f188 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-12/README.md @@ -0,0 +1,2 @@ +### Relevant Articles +- Difference between "*" and "Any" in Kotlin generics - Link to be updated diff --git a/core-kotlin-modules/core-kotlin-12/pom.xml b/core-kotlin-modules/core-kotlin-12/pom.xml new file mode 100644 index 000000000..e1572ace7 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-12/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + core-kotlin-12 + core-kotlin-12 + jar + + + com.baeldung + core-kotlin-modules + 1.0.0-SNAPSHOT + + + + src/main/kotlin + src/test/kotlin + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + compile + compile + + compile + + + + + + + diff --git a/core-kotlin-modules/core-kotlin-12/src/main/kotlin/com/baeldung/casting/Candy.kt b/core-kotlin-modules/core-kotlin-12/src/main/kotlin/com/baeldung/casting/Candy.kt new file mode 100644 index 000000000..698fcc1d1 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-12/src/main/kotlin/com/baeldung/casting/Candy.kt @@ -0,0 +1,8 @@ +package com.baeldung.casting + +sealed class Candy(val name: String) { + override fun toString() = name +} + +object ChocolateBar: Candy("Chocolate Bar") +object Lollipop : Candy("Lollipop") \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-12/src/main/kotlin/com/baeldung/casting/SpookyTrinket.kt b/core-kotlin-modules/core-kotlin-12/src/main/kotlin/com/baeldung/casting/SpookyTrinket.kt new file mode 100644 index 000000000..ff153cb44 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-12/src/main/kotlin/com/baeldung/casting/SpookyTrinket.kt @@ -0,0 +1,7 @@ +package com.baeldung.casting + +sealed class SpookyTrinket(val name: String) { + override fun toString() = name +} +object FakeSpider : SpookyTrinket("Fake Spider") +object VampireFang : SpookyTrinket("Vampire Fang") \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-12/src/main/kotlin/com/baeldung/casting/TreatDispenser.kt b/core-kotlin-modules/core-kotlin-12/src/main/kotlin/com/baeldung/casting/TreatDispenser.kt new file mode 100644 index 000000000..7da30f8ac --- /dev/null +++ b/core-kotlin-modules/core-kotlin-12/src/main/kotlin/com/baeldung/casting/TreatDispenser.kt @@ -0,0 +1,35 @@ +package com.baeldung.casting + +import kotlin.collections.MutableList +import kotlin.collections.mutableListOf +import kotlin.collections.firstOrNull + +class TreatDispenser(private val treats: MutableList = mutableListOf()) { + + // Dispense the first treat + fun dispenseTreat(): T? { + return if (treats.isNotEmpty()) treats.removeFirst() else null + } + + // Peek at the next treat without removing it + fun peekNextTreat(): T? { + return treats.firstOrNull() + } + + // Add a treat to the dispenser + fun addTreat(treat: T) { + treats.add(treat) + } +} + +// Function using * (Star Projection) +fun peekAtNextTreat(dispenser: TreatDispenser<*>) { + val nextTreat = dispenser.peekNextTreat() + println("The next treat is: $nextTreat") +} + +// Function using Any (restricted to non-nullable types) +fun peekAtNextTreatAny(dispenser: TreatDispenser) { + val nextTreat = dispenser.peekNextTreat() + println("The next treat is: $nextTreat") +} diff --git a/core-kotlin-modules/core-kotlin-12/src/test/kotlin/com/baeldung/casting/TreatDispenserUnitTest.kt b/core-kotlin-modules/core-kotlin-12/src/test/kotlin/com/baeldung/casting/TreatDispenserUnitTest.kt new file mode 100644 index 000000000..1de0854cc --- /dev/null +++ b/core-kotlin-modules/core-kotlin-12/src/test/kotlin/com/baeldung/casting/TreatDispenserUnitTest.kt @@ -0,0 +1,65 @@ +package com.baeldung.casting + +import org.junit.Test +import org.junit.jupiter.api.Assertions.* + +class TreatDispenserUnitTest { + + @Test + fun `dispenseTreat should return the first treat`() { + + val dispenser = TreatDispenser() + dispenser.addTreat(ChocolateBar) + dispenser.addTreat(Lollipop) + + assertEquals(ChocolateBar, dispenser.dispenseTreat()) + assertEquals(Lollipop, dispenser.dispenseTreat()) + assertNull(dispenser.dispenseTreat()) + } + + @Test + fun `peekNextTreat should show the next treat without removing it`() { + val dispenser = TreatDispenser() + dispenser.addTreat(Lollipop) + + assertEquals(Lollipop, dispenser.peekNextTreat()) + assertEquals(Lollipop, dispenser.peekNextTreat()) + } + + @Test + fun `peekAtNextTreat using star projection works for all types`() { + val candyDispenser = TreatDispenser() + candyDispenser.addTreat(ChocolateBar) + + val trinketDispenser = TreatDispenser() + trinketDispenser.addTreat(VampireFang) + trinketDispenser.addTreat(FakeSpider) + + // Test with Candy dispenser + assertDoesNotThrow { + peekAtNextTreat(candyDispenser) + } + + // Test with Trinket dispenser + assertDoesNotThrow { + peekAtNextTreat(trinketDispenser) + } + } + + @Test + fun `peekAtNextTreatAny fails for non-Any dispensers`() { + val candyDispenser = TreatDispenser() + candyDispenser.addTreat(ChocolateBar) + + // This would fail type checking, hence commented: + // peekAtNextTreatAny(candyDispenser) // Error: Type mismatch + + val anyDispenser = TreatDispenser() + anyDispenser.addTreat("Surprise Treat") + + assertDoesNotThrow { + peekAtNextTreatAny(anyDispenser) + } + } + +} diff --git a/core-kotlin-modules/pom.xml b/core-kotlin-modules/pom.xml index e41a4e4fd..2d5bb02c8 100644 --- a/core-kotlin-modules/pom.xml +++ b/core-kotlin-modules/pom.xml @@ -4,7 +4,6 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.baeldung core-kotlin-modules pom @@ -26,6 +25,7 @@ core-kotlin-9 core-kotlin-10 core-kotlin-11 + core-kotlin-12 core-kotlin-advanced core-kotlin-advanced-2 core-kotlin-advanced-3