Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to solve violation of Finite Bound Restriction in Kotlin? [duplicate]

Assume that I have this declaration in Java, it's okay.

abstract class Start<T extends End> {
    public T end;
}

abstract class End<T extends Start> {
    public T start;
}

However, it's not okay in Kotlin, since Kotlin has restriction for "cyclic" type parameter.

abstract class Start<T : End<*>> {
    lateinit var end: T
}

abstract class End<T : Start<*>> {
    lateinit var start: T
}

Is there any approach to solve this in Kotlin, so that I can have generic types that depend on each other?

like image 816
fikr4n Avatar asked Oct 11 '17 07:10

fikr4n


People also ask

What is the difference between * and any in Kotlin generics?

When we define a collection with "*", it should contain the object of only that type. There should not be any mix and match between the data types inside a collection. If we use "Any", we can mix and match the data types, which means we can have multiple data types in a collection.

What is the out keyword in Kotlin?

"Out" keyword is extensively used in Kotlin generics. Its signature looks like this − List<out T> When a type parameter T of a class C is declared out, then C can safely be a super type of C<Derived>. That means, a Number type List can contain double, integer type list.

How do I call generic method Kotlin?

Kotlin generic example When we call the generic method <T>printValue(list: ArrayList<T>) using printValue(stringList), the type T of method <T>printValue(list: ArrayList<T>)will be replaced by String type.

How do I create a generic variable in Kotlin?

We can make generic variable using this kind of syntax: "val destinationActivity: Class<*>". Main part is "*".


1 Answers

It is impossible to use just one type parameter. Introducing Self type, which is natively supported in some other languages, is necessary. However, in kotlin you will have to introduce the Self type by yourself, because JetBrains officially turned down the request of adding self type.

abstract class Start<Self: Start<Self, T>, T: End<T, Self>> {
    lateinit var end: T
}

abstract class End<Self: End<Self, T>, T: Start<T, Self>> {
    lateinit var start: T
}

PS: This Self may later induce tediously long type. Proceed with caution.

like image 78
glee8e Avatar answered Sep 18 '22 08:09

glee8e