angryziber / kotlin-puzzlers

A collection of Kotlin Puzzlers
422 stars 58 forks source link

inner class with generics #67

Closed shalva97 closed 3 years ago

shalva97 commented 4 years ago

will it compile and write my name?

class Being<T>(val name: T? = null) {

    fun greet(being: Matter) {
        (being as this.Human).sayHello(name)
    }

    inner class Human: Matter() {
        fun sayHello(name: T?) {
            print("hello $name")
        }
    }

    open class Matter
}

fun main() {
    val human = Being("shalva97")
    human.greet(Being.Matter())
}
michaem commented 4 years ago

This code never be compile, because operator 'as' should always has static type on the right side, but there's keyword 'this', which a dynamic type of Being class itself.

Also this code has a design issue. Seems Being type has common semantic, but Human is more detail logic. When you call Being("shalva97"), you tell 'abstract logic' of Being the detail implementation of Human by passing name 'shalva97'. It seems LSP error from SOLID, but I could mistake)

I'm not sure that this code is a puzzler)

TWiStErRob commented 4 years ago

@michaem I think the focus here is (name: T?), will that be using <T> from Being's scope or not? It may be a bit too much code around it, which hides the "question".

shalva97 commented 4 years ago

yes, it is about the scope and also a bit confusing error from Intellij.

I cannot create inner class without parent so i though writing "this.Human" should work and now i read from Michaem that operator 'as' should always has static type on the right side... so i guess it is just my lack of experience with Kotlin...

and here is the picture of an error that confused me a lot... later i figured it out that i should write (being as Being<T>.Human). but i wonder wouldnot it be better if (being as this.Human) worked?

image