I have this code given in a tutorial book on a chapter on generics:
class LootBox<T> (item: T) {
var open = false
private var loot: T = item
fun fetch(): T? {
return loot.takeIf { open }
}
fun <R> fetch(lootModFunction: (T) -> R): R? {
return lootModFunction(loot).takeIf { open }
}
}
class Fedora (val name: String, val value: Int)
class Coin (val value: Int)
fun main() {
val lootBoxOne = LootBox(Fedora("a generic-looking fedora", 15))
val lootBoxTwo = LootBox(Coin(15))
lootBoxOne.open = true
lootBoxOne.fetch()?.run {
println("You retrieve ${this.name} from the box!")
}
val coin = lootBoxOne.fetch() {
Coin(it.value * 3)
}
coin?.let {println(it.value)}
}
-
First of all, how can we have 2 different functions with the same name? Is it allowed because they have different signatures? One
fetch()
function that doesn’t have any parameters, and onefetch()
that does? -
Second of all, what’s the point of the variable “item” in the primary constructor, and then immediately reassigning it into a new variable, “loot”? Is that just standard procedure for generic constructors? Why not just use
class LootBox<T> (private var loot: T)
-
Third, and most important question, what is going on with the lambda parameter of the fetch function here? I don’t understand how this is working. I can understand that the fetch function is setting up a parameter named
lootModFunction
of type(T) -> R
. So, when the function is called, it needs an argument that will pass an object of type T (which same as the type the function is called on) and returns a different type, R. So how doesCoin(it.value * 3)
function as(T) -> R
?