Home > Enterprise >  Automatically converting function
Automatically converting function

Time:10-19

If I have the following code:

fun main() {
   println(Example("test", 1))
}

class Example(private val text: String, private val num: Int) {
    override fun toString(): String {
        return "String: $text $num"
    }
}

and it works.

Is there any way to do this for types different from string?

Example:

class Example {
    
    fun toList(): List {
        //Convert to list...
    }
}
thisFunctionRequireList(Example2())

CodePudding user response:

I will first explain how

println(Example1())

works, and from there, create something similar.

First, note that println has many overloads. This println call does not call the println(String) overload. It calls the println(Any?) overload.

The println(Any?) overload is implemented to transform the Any parameter into a String using toString, and then calls the println(String) overload using that string. Here is the Kotlin/Native implementation:

public actual fun println(message: Any?) {
    println(message.toString())
}

Note that it is able to do this, only because Any?, and by extension Any, declares the toString method. This allows it to convert any value you pass, to a String. At runtime, this gets dispatched to the toString override that you declared in Example1.

Therefore, it is not because you overrode toString, that you were able to call println with Example. It is because

  • println has an overload that takes Any, allowing you to pass anything into it
  • Any also declares a toString that you can override, which println(Any) also uses in its implementation

Any does not declare a toList method, so we can't use Any if we want to do the same for List.

We can declare a new interface for types that can be converted to lists:

interface ConvertibleToList<T> {
    fun toList(): List<T>
}

This is like an Any, but only for types that implement it. Example2 can then implement the interface:

class Example2: ConvertibleToList<String> {
    
    override fun toList(): List<String> {
        //Convert to list...
    }
}

Now suppose there is an existing function that takes a List<String>:

fun doThingsToStrings(strings: List<String>) { ... }

You can add a new overload of this, with the parameter type being ConvertibleToList<T>:

fun doThingsToStrings(strings: ConvertibleToList<String>) = doThingsToStrings(strings.toList())

doThingsToStrings becomes just like println, with one overload taking the "exact" type (List<String>), and another overload taking types that can be converted to the "exact" type (ConvertibleToList<String>).

Now you can call doThingsToStrings with Example2()!

  • Related