Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin optional generic parameter

Tags:

kotlin

Here is the problem I am trying to resolve, I am trying to use a void type as a generic type:

class Parent {
    private abstract class Item<out T>(val data: T)
    // This subclass should contain data
    private class ItemContent(val data: String): Item<String>(data)
    // This subclass doesn't contain data
    private class ItemNoContent: Item<Any?>(null)
}

Some base classes like ItemNoContent doesn't contain meaningful data so I make ItemNoContent extends Item(null). It works but I feel that the use of Any? and null is inappropriate here. Is there a more Kotlin way to solve this optional generic problem?

like image 731
darklord Avatar asked Jul 05 '18 16:07

darklord


People also ask

How do I make generic optional?

To make a generic type optional, you have to assign the void as the default value. In the example below, even though the function takes a generic type T, still you can call this function without passing the generic type and it takes void as default.

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 "*".

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.

Does Kotlin have type erasure?

Type Erasure. As with Java, Kotlin's generics are erased at runtime. That is, an instance of a generic class doesn't preserve its type parameters at runtime. For example, if we create a Set<String> and put a few strings into it, at runtime we're only able to see it as a Set.


3 Answers

You can also use Item<Unit>(Unit) which represents a void value in Kotlin.

like image 145
Pawel Avatar answered Oct 21 '22 10:10

Pawel


Some base classes like ItemNoContent doesn't contain meaningful data

Then why extend a class which is supposed to have it? While Unit and null are both options, consider also

private abstract class Item<out T>
private abstract class ItemWithContent<out T>(val data: T) : Item<T>
...
// object may make more sense than class here
private object ItemNoContent : Item<Nothing>()
like image 29
Alexey Romanov Avatar answered Oct 21 '22 12:10

Alexey Romanov


I would tweak the inheritance like this:

abstract class Item

abstract class ItemWithContent<T>(val d: T): Item()

class ItemWithStringContent(d: String): ItemWithContent<String>(d)

class ItemWithNoContent: Item()

This way, there is not need to use Unit or Nothing.

Usage:

fun main(args: Array<String>){
    val t: Item = ItemWithStringContent("test")
    println((t as? ItemWithStringContent)?.d)
}
like image 22
Willi Mentzel Avatar answered Oct 21 '22 11:10

Willi Mentzel