Error Override by a function with reified type parameter


#1

I have created following lnterface

interface MsgInterface{
  fun<M> Send(msg: M)
}

class MsgProcessor : MsgInterfce {
    override inline fun<reified M> Send(msg:M){
    //Process send message
   }
 }

I am getting following error message while compiling

"Override by a function with reified type parameter"

How to solve this issue?


#2

The problem is that it’s impossible to inline virtual members. This can be shown in a small example.

interface MsgInterface {
   inline <M>fun send(msg: M)   // this is not allowed, but let's pretend
}

class A: MsgInterface { ... }
class B: MsgInterface { ... }

val msg = listOf(A(), B())
msg.forEach{
    it.send()   // even though send is "inline" it can't be because the compiler does not know which "send" to use
}

What you can do is this

interface Foo {
    fun foo()
}
class A: Foo {
    override inline fun foo() {}
}

This will only generate a warning. If you call someA.foo() the compiler can inline it. If you however call (someA as Foo).foo() the compiler can’t because of what I showed above.

The problem you have is that you try to use reified. Reified is a special keyword that allows kotlin to get around a restriction on the JVM. The problem on the JVM is that you only know the type of generics at compile time and not at runtime. That’s why you can’t normally use T::class. Reified works by inlining the function therefor removing this restriction. The problem is now that you can’t inline (someA as Foo).foo().

This depends on what you are trying to achieve. You have to change your code so it does not rely on reified to work.


#3

Hi Wasabi,

I have to use `M::class` on inside the send method. so i have used `<reified M>` keyword  

Is it not possible to avoid the error “Override by a function with reified type parameter”?


#4

No. As I explained you can not use reified for virtual(orverride/open) functions. What you could do is change your interface to this

interface MsgInterface {
    fun <M> Send(msg: M, klass: KClass<M>)
}

That way you don’t need to use M::class inside of your function but can use klass instead. It’s the way this is often done in plain java. It’s not as nice as reified but it works.


#5

@Wasabi375 I am getting error in klass: KClass parameter.
Its saying
Type argument is not within its bounds
Expected Any
Found M
Any suggestion for solution of this?


#6

Can you show an example of your problem? Right now I have no idea how I could help you :wink:

I guess your problem has to do with variance but I’m not sure.


#7

kclass-issue

Please check this. I just tried copying your code in an android studio and got this error. I am using kotlin 1.2.71


#8

Woops, sry, you need to add an upper bound to M. The reason is that the default upper bound for a generic type is Any? (meaning it can be null) but KClass only allows for non nullable types. So you need to add Any as the upper bound for M.

Also since you are using Android Studio, you might want to start using the intentions. All you need to do is press Alt+Enter on an error like this and you get a dropdown explaining the error and in many cases also giving you a way to automatically fix it.


It seems I can’t edit the original post so here is the code again

fun <M: Any> send(msg: M, klass: KClass<M>)

#9

Now its working. Thanks :slight_smile: