Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin Inheritance with Boolean generics

Tags:

android

kotlin

I have a problem when I try to override a generics method with Boolean,Double,Integer,Float. It works with Date. (May because is it Serializable?)

The interface:

interface AnInterface<C, T> {
    fun doSomething(items: List<T>, vararg value: C): List<T>
}

An abstact implementation: (No override doSomething)

abstract class BaseClass<C, T> : AnInterface<C, T> { ... }

It's work:

class AnImplementetion<T> : BaseClass<Date, T>() {

    override fun doSomething(items: List<T>, vararg value: Date): List<T> {
            // It works
    }
}

It doesn't work:

class AnAnotherImplementetion<T> : BaseClass<Boolean, T>() {

    override fun doSomething(items: List<T>, vararg value: Boolean): List<T> {
            // It doens't
    }
}

The IDE always want to implement the doSomething. When I implement it with IDE it creates always the same one.

Error message:

Class 'AnAnotherImplementetion' is not abstract and does not implement abstract base class member
public abstract fun fun doSomething(items: List<T>, vararg value: Boolean): List<T> defined in BaseClass

'doSomething' overrides nothing

How can I fix it? Thank you

UPDATE: It works with JAVA. But Why doesn't with Kotlin?

public class AnAnotherImplementetion<T> extends BaseClass<Boolean, T> {

    @NotNull
    @Override
    public List<T> doSomething(@NotNull List<? extends T> items,  Boolean... value) {
        // It works with JAVA

    }
}

UPDATE 2:

It works when vararg is nullable.

interface AnInterface<C, T> {
    fun doSomething(items: List<T>, vararg value: C?): List<T>
}
like image 406
vihkat Avatar asked Aug 14 '18 07:08

vihkat


Video Answer


2 Answers

It looks like a bug in kotlin compiler. As I know during compiling it decides to use primitive type (int) or wrap (Integer). Java generics can't work with primitives, so compiler uses wrap for generic-type, BUT then compiler sees, that method param is never null and replaces it with primitive-type, and type-conflict appears. And here nullable saves a day.
But I'm not sure, it's just a guess.

like image 125
Ufkoku Avatar answered Oct 19 '22 14:10

Ufkoku


The kotlin reference regarding basic types contains a passage which explains how it should deal with primitive types and generics in particular.

Obviously the latter is not working correctly. When generics are involved it should box the types which it either doesn't do or which the compiler complains about falsely.

You should open a bug at https://youtrack.jetbrains.com/ and link it here too. Maybe it was also a conscious design decision.

A workaround is to use the nullable type Boolean? as that will work as it is described in the reference. It will be boxed and therefore will work with generics.

Alternatively, if you are on the JVM, you can use the java.lang.Boolean instead. It's the object type of the primitive boolean and even though it is discouraged to use the Java types in Kotlin it is a possible workaround until Kotlin behaves as it should. However... testing it, Kotlin does some more magic around it so that its usage isn't that helpful neither. You would then even need to cast the java.lang.Boolean.TRUE as java.lang.Boolean. That's clearly not helpful at all. Opening a bug is the best you can do here.

like image 1
Roland Avatar answered Oct 19 '22 13:10

Roland