How to override Number.toString()?

So, the reason I want to do this is because I want to translate digits into my native language.
Normally:

val num = 1234
println(num) // toString() is called to stringify num before printing.

This is how kotlin works. But if I want the number in my native language by default, one solution might be to override Number.toString() to covert the digits of the orginal toString() output to print the digits in the language I want to.
Now the question is how do I actually do this? I tried something like this:

val digits = "০১২৩৪৫৬৭৮৯".toList()

open class Number {
    override fun toString() : String {
        return this.toString().map { it ->
            if (!it.isDigit()) return@map it
            return@map digits[it.digitToInt()]
        }.joinToString("")
    }
}

fun main() {
    println(digits)
    val test = 1234567890.0123456789
    println(test) // still prints in english
}

But the following function works which means the problem is toString() is not being overridden properly.

fun Number.tr(): String {
    return this.toString().map { it ->
        if (!it.isDigit()) return@map it
        return@map digits[it.digitToInt()]
    }.joinToString("")
}

Now how do I get the result I want?

You can’t override toString() – or any method – in Int or Long or any of the existing Number subclasses.

But that wouldn’t be a good approach, anyway; the display format isn’t an inherent property of the number, but instead of the way you display it.

The standard way to customise how numbers are displayed is with a NumberFormat. You may be able to get one explicitly for your locale – but you may find that the default one for your locale (using NumberFormat.getInstance()) does what you want. (The latter would be even better, as it would work for people all over the world, using the right format for wherever they are.)

You can then call its .format(myNumber) method to convert any Number to a String ready to display.

1 Like

Ok, the following seems to work:

import java.text.NumberFormat
import java.util.Locale

fun main() {
    val nf = NumberFormat.getInstance(Locale.of("bn", "BD"));
    val test = 1234567890.0123456789
    println(nf.format(test)) // ১,২৩৪,৫৬৭,৮৯০.০১২
}

I think the best way to think about toString() is that it provides information about some piece of data for debugging or logging. It’s something that only a programmer cares about. If you want to display the contents of the data to the user, or convert it to JSON to send to a server, use some other method.

5 Likes