2

Code snippet

fun main() {
    val myClass : AbsClass<Any> = MyClass()
    // Error - type mismatch

    val myClass : AbsClass<*> = MyClass() 
    // Not Error, but parameter of 'foo' is 'Nothing'

    val myClass : AbsClass<Any> = MyClass() as AbsClass<Any> 
    // It's correct works with unchecked cast warning and unnecessary casting code.

    myClass.foo(MyModel())
}

class MyClass() : AbsClass<MyModel>() {
}

abstract class AbsClass<T> {
    fun foo(value:T){}
}

data class MyModel(val number:Int = 0)

Question

I want writing code as val myClass : AbsClass<Any> = MyClass() but, it shows type mismatch error. How to solve this problem(avoid type casting codeas AbsClass<Any>)?

4
  • I think this is not possible as foo has in semantics. This only works if you can change AbsClass<T> to AbsClass<out T> Commented Mar 5, 2019 at 7:12
  • Not familiar with Kotlin, but I believe generics in Kotlin is similar to what in Java, which is not covariant. i.e. Foo<Derived> is-not-a Foo<Parent>. So you cannot assign a AbsClass<MyModel> instance to a AbsClass<Any> reference. Commented Mar 5, 2019 at 8:09
  • Actually generics in Kotlin are covariant, you can read more about that here Commented Mar 5, 2019 at 15:34
  • @AlexanderEgger If you do that you can't use this fun foo(value:T){} IDE will complain saying Type parameter T is declared as 'out' but occurs in 'in' position in type T AbsClass<out T> Commented Sep 2, 2022 at 16:28

1 Answer 1

7

You should use:

val myClass: AbsClass<out Any> = MyClass()` or `val myClass: AbsClass<in Nothing> = MyClass()

The out keyword means you want any subtype could be assigned to supertype. MyModel can by assigned to Any, so it's ok.

The in keyword means you expect any supertype could be assigned to subtype (in our case Nothing), so you can use your MyModel because it is the supertype of Nothing.

This way, without providing any information of expected type (you can specify, like AbsClass<T : MyAbstractModel>), in my opinion, there is really few possibilities without casting or reflection.

It's type variance and it's one of the most difficult ideas in OOP. More you can read here: https://kotlinlang.org/docs/reference/generics.html#variance

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

2 Comments

Don't know why OP accepted your answer but it is wrong one. In both case you will get Type mismatch. Required: Nothing, Found: MyModel when you try to call this myClass.foo(MyModel())
Yep, but the question was about “how to declare”. That's why I have tried to explain later – using so wide type does not give a lot of possibilities.

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.