Search code examples
templateskotlinextension-methods

Sharing implementations of extension functions between Float and Double in Kotlin


NOTE: This question is not about generic classes, it's about generic functions. (I don't believe it to be a duplicate of this one: it is more specific than that.)

In our project, we have a handful of utility functions to extend Double and Float, such as toFixed (inspired by Javascript's Number.toFixed)

fun Double.toFixed(digits: Int):String = java.lang.String.format("%.${digits}f", this)
fun Float.toFixed(digits: Int):String = java.lang.String.format("%.${digits}f", this)

As you can see, Double.toFixed and Float.toFixed have an identical implementation.

Because there are several other, more complicated extension functions like this, improvements and bug fixes in one version (say, Double.toPrecision) have to be manually kept in sync (with Float.toPrecision), which is boring and error prone.

I experimented with moving the duplicated implementations into a shared <templated> function, but (rightly) it can't access this in the context of an unbound function.

To illustrate, I was hoping for something like this:

private fun <T>toFixed(digits: Int):String = java.lang.String.format("%.${digits}f", this)
fun Double.toFixed = ::toFixed<Double>
fun Float.toFixed = ::toFixed<Float>

If any language can rock this, surely Kotlin can! Thoughts?


Solution

  • An extension on a generic type can be achieved by using fun <T> T.toFixed(...). Doing that, this is accessible.

    The Problem then is, that the extenstion can be used on any type! You can use upper bounds on your T to restrict it:

    fun <T: Number> T.toFixed(...)

    If you really have to restrict the extension to only Float and Double it's necessary to extend the concrete types only. Have a look at the Koltin math library in addition, might be helpful :) (Available with 1.2-Beta):
    https://github.com/JetBrains/kotlin/blob/1.2-Beta/js/js.libraries/src/core/math.kt