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?
Inner classesA inner class declared in the same outer class (or in its descendant) can inherit another inner class.
Kotlin Inner class Inner class is a class which is created inside another class with keyword inner. In other words, we can say that a nested class which is marked as "inner" is called inner class. Inner class cannot be declared inside interfaces or non-inner nested classes. class outerClass{ //outer class code.
Everything in Kotlin is by default final, hence, we need to use the keyword open in front of the class declaration to make it inheritable for other classes. Kotlin uses operator ":" to inherit a class.
An inner class has nothing to do with a subclass. You use inheritance if you like to extend a parent class or where a "is a" relation exists. This is not necessarily the case for inner classes. They can (for example) be used as small helper classes, like in Map implementations, there the Entry class is nested.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With