Skip to content

Commit 35f7d4f

Browse files
authored
KTLN-622: Implement code for the article differentiating Kotlin Any vs * in generics. (#1142)
* KTLN-622: Implement code for the article differentiating Kotlin Any vs * in generics. * KTLN-622: Implement code for the article differentiating Kotlin Any vs * in generics. * KTLN-622: Implement code for the article differentiating Kotlin Any vs * in generics. * KTLN-622: Implement code for the article differentiating Kotlin Any vs * in generics. * KTLN-622: Implement code for the article differentiating Kotlin Any vs * in generics.
1 parent 0691d79 commit 35f7d4f

File tree

8 files changed

+156
-1
lines changed

8 files changed

+156
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
### Relevant Articles
2-
- [Convert a Data Class to ByteBuffer in Kotlin](https://www.baeldung.com/kotlin/convert-data-class-to-bytebuffer)
2+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
### Relevant Articles
2+
- Difference between "*" and "Any" in Kotlin generics - Link to be updated
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5+
http://maven.apache.org/xsd/maven-4.0.0.xsd">
6+
<modelVersion>4.0.0</modelVersion>
7+
<artifactId>core-kotlin-12</artifactId>
8+
<name>core-kotlin-12</name>
9+
<packaging>jar</packaging>
10+
11+
<parent>
12+
<groupId>com.baeldung</groupId>
13+
<artifactId>core-kotlin-modules</artifactId>
14+
<version>1.0.0-SNAPSHOT</version>
15+
</parent>
16+
17+
<build>
18+
<sourceDirectory>src/main/kotlin</sourceDirectory>
19+
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
20+
<plugins>
21+
<plugin>
22+
<groupId>org.jetbrains.kotlin</groupId>
23+
<artifactId>kotlin-maven-plugin</artifactId>
24+
<version>${kotlin.version}</version>
25+
<executions>
26+
<execution>
27+
<id>compile</id>
28+
<phase>compile</phase>
29+
<goals>
30+
<goal>compile</goal>
31+
</goals>
32+
</execution>
33+
</executions>
34+
</plugin>
35+
</plugins>
36+
</build>
37+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.baeldung.casting
2+
3+
sealed class Candy(val name: String) {
4+
override fun toString() = name
5+
}
6+
7+
object ChocolateBar: Candy("Chocolate Bar")
8+
object Lollipop : Candy("Lollipop")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.baeldung.casting
2+
3+
sealed class SpookyTrinket(val name: String) {
4+
override fun toString() = name
5+
}
6+
object FakeSpider : SpookyTrinket("Fake Spider")
7+
object VampireFang : SpookyTrinket("Vampire Fang")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.baeldung.casting
2+
3+
import kotlin.collections.MutableList
4+
import kotlin.collections.mutableListOf
5+
import kotlin.collections.firstOrNull
6+
7+
class TreatDispenser<T>(private val treats: MutableList<T> = mutableListOf()) {
8+
9+
// Dispense the first treat
10+
fun dispenseTreat(): T? {
11+
return if (treats.isNotEmpty()) treats.removeFirst() else null
12+
}
13+
14+
// Peek at the next treat without removing it
15+
fun peekNextTreat(): T? {
16+
return treats.firstOrNull()
17+
}
18+
19+
// Add a treat to the dispenser
20+
fun addTreat(treat: T) {
21+
treats.add(treat)
22+
}
23+
}
24+
25+
// Function using * (Star Projection)
26+
fun peekAtNextTreat(dispenser: TreatDispenser<*>) {
27+
val nextTreat = dispenser.peekNextTreat()
28+
println("The next treat is: $nextTreat")
29+
}
30+
31+
// Function using Any (restricted to non-nullable types)
32+
fun peekAtNextTreatAny(dispenser: TreatDispenser<Any>) {
33+
val nextTreat = dispenser.peekNextTreat()
34+
println("The next treat is: $nextTreat")
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.baeldung.casting
2+
3+
import org.junit.Test
4+
import org.junit.jupiter.api.Assertions.*
5+
6+
class TreatDispenserUnitTest {
7+
8+
@Test
9+
fun `dispenseTreat should return the first treat`() {
10+
11+
val dispenser = TreatDispenser<Candy>()
12+
dispenser.addTreat(ChocolateBar)
13+
dispenser.addTreat(Lollipop)
14+
15+
assertEquals(ChocolateBar, dispenser.dispenseTreat())
16+
assertEquals(Lollipop, dispenser.dispenseTreat())
17+
assertNull(dispenser.dispenseTreat())
18+
}
19+
20+
@Test
21+
fun `peekNextTreat should show the next treat without removing it`() {
22+
val dispenser = TreatDispenser<Candy>()
23+
dispenser.addTreat(Lollipop)
24+
25+
assertEquals(Lollipop, dispenser.peekNextTreat())
26+
assertEquals(Lollipop, dispenser.peekNextTreat())
27+
}
28+
29+
@Test
30+
fun `peekAtNextTreat using star projection works for all types`() {
31+
val candyDispenser = TreatDispenser<Candy>()
32+
candyDispenser.addTreat(ChocolateBar)
33+
34+
val trinketDispenser = TreatDispenser<SpookyTrinket>()
35+
trinketDispenser.addTreat(VampireFang)
36+
trinketDispenser.addTreat(FakeSpider)
37+
38+
// Test with Candy dispenser
39+
assertDoesNotThrow {
40+
peekAtNextTreat(candyDispenser)
41+
}
42+
43+
// Test with Trinket dispenser
44+
assertDoesNotThrow {
45+
peekAtNextTreat(trinketDispenser)
46+
}
47+
}
48+
49+
@Test
50+
fun `peekAtNextTreatAny fails for non-Any dispensers`() {
51+
val candyDispenser = TreatDispenser<Candy>()
52+
candyDispenser.addTreat(ChocolateBar)
53+
54+
// This would fail type checking, hence commented:
55+
// peekAtNextTreatAny(candyDispenser) // Error: Type mismatch
56+
57+
val anyDispenser = TreatDispenser<Any>()
58+
anyDispenser.addTreat("Surprise Treat")
59+
60+
assertDoesNotThrow {
61+
peekAtNextTreatAny(anyDispenser)
62+
}
63+
}
64+
65+
}

core-kotlin-modules/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<module>core-kotlin-9</module>
2626
<module>core-kotlin-10</module>
2727
<module>core-kotlin-11</module>
28+
<module>core-kotlin-12</module>
2829
<module>core-kotlin-advanced</module>
2930
<module>core-kotlin-advanced-2</module>
3031
<module>core-kotlin-advanced-3</module>

0 commit comments

Comments
 (0)