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