9

I'm trying to create a hierarchy of few classes, each one overriding some behavior in inner classes of it's parent (Specifically iterators, but it does not matter). Basically, it looks like this:

open class SuperClass<T>{
    protected open inner class InnerClass{
        fun someLogic(){
            println("some logic happened")
        }

        open fun someOverridableLogic(){
            println("some logic happened")
        }
    }
}

class ChildClass<T> : SuperClass<T>(){
    protected inner class ChildInnerClass:InnerClass{
        override fun someOverridableLogic(){
            super.someOverridableLogic()
            println("some OTHER logic happened")
        }
    }
}

Compiler refuses to work with this code, expecting type parameter on InnerClass when ChildInnerClass inherits from it. However, after adding parameter like this:

protected inner class ChildInnerClass:InnerClass<T>

compiler suddenly does not expect any type parameters!

Java equivalent of this compiles and executes as expected, without type parameters:

public class SuperClass<T> {
    protected class InnerClass{
        public void someLogic(){
            System.out.println("some logic happened");
        }

        public void someOverridableLogic(){
            System.out.println("some logic happened");
        }
    }
}


public class ChildClass<T> extends SuperClass<T>{
    protected class ChildInnerClass extends InnerClass{
        @Override
        public void someOverridableLogic() {
            super.someOverridableLogic();
            System.out.println("some OTHER logic happened");
        }
    }
}

So, am i doing something wrong in Kotlin, or is it simply a language restriction i wasn't aware about?

1 Answer 1

8

The compiler is not expecting a type argument on InnerClass but on SuperClass in SuperClass.InnerClass. This is a known issue: Capture generics in inner classes : KT-9208.

For now you can do the following:

open class SuperClass<T> {
    protected open inner class InnerClass {
        fun someLogic() {
            println("some logic happened")
        }

        open fun someOverridableLogic() {
            println("some logic happened")
        }
    }
}

class ChildClass<T> : SuperClass<T>() {
    protected inner class ChildInnerClass : SuperClass<T>.InnerClass() {
        override fun someOverridableLogic() {
            super.someOverridableLogic()
            println("some OTHER logic happened")
        }
    }
}

See also Hadoop Context type parameters in Kotlin for a similar example and answer.

Sign up to request clarification or add additional context in comments.

4 Comments

Piggybacking a question as I'm new to Kotlin: I'm trying to get my head around this and the code on the answer doesn't compile for me. I had to add the type parameter on InnerClass too, so it ended up being inner class ChildInnerClass : SuperClass<T>.InnerClass<T>() which I think is what the linked answer suggests to do... am I missing something?
You need to specify type parameter on InnerClass only if you defined it with a type parameter (protected open inner class InnerClass<T>) In this code InnerClass does not require type parameters and instead uses T from it's parent, SuperClass
@Augusto if the code on the answer doesn't compile for you then I am guessing you made some changes to InnerClass, etc. As such, for clarity, I've updated the code in the answer to include the SuperClass declaration. You should be able to copy and paste the example into a new Kotlin file and it should compile without any problems. Please let us know if it doesn't for you.
Silly me! I added <T> to SuperClass.InnerClass at some point while playing with the code. Thanks for clarifying this!!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.