Kotlin: ¿Hay alguna manera de limpiar las sobrecargas de numbers?

A menudo me encuentro creando muchas sobrecargas para los types de numbers porque Kotlin no hace conversiones implícitas para los no literales. Esto da como resultado una gran cantidad de funciones de sobrecarga duplicadas, que son toneladas y toneladas de text repetitivo.

Un ejemplo del dolor que tengo al hacer esto se puede ver aquí: https://github.com/Jire/Arrowhead/blob/master/src/main/kotlin/org/jire/arrowhead/Source.kt

Entiendo la razón por la cual las conversiones implícitas pueden causar errores, pero creo que en la mayoría de los casos, especialmente para las conversiones de "ampliación" como Byte -> Int e Int -> Long donde los datos no se pierden, debería haber una mejor manera.

Entonces … mi pregunta es ¿cómo lidias con esto? ¿Hay alguna forma creativa de resolver este problema?

Respondiendo a su pregunta: puede usar una function genérica con Number . Entonces aceptará cualquier subtipo de Number . Luego puede convertir el valor en cualquier otro tipo numérico:

 fun boo(x: Number) { val y = x.toLong() println(y is Long) } 

El único inconveniente de esto es el autoboxing, pero eso no debería importar para su caso.

En cuanto al código que publicaste: creo que tienes algunos errores arquitectónicos que causan esta situación. Aquí está tu API sin demasiados detalles:

 interface Source { fun read(address: Long, data: Pointer, bytesToRead: Int) fun read(address: Int, data: Pointer, bytesToRead: Int) = read(address.toLong(), data, bytesToRead) fun read(address: Long, data: Memory, bytesToRead: Int = data.size().toInt()) = read(address, data as Pointer, bytesToRead) fun read(address: Int, data: Memory, bytesToRead: Int = data.size().toInt()) = read(address.toLong(), data, bytesToRead) fun read(address: Long, struct: Struct, bytesToRead: Int = struct.size()) = read(address, struct.pointer, bytesToRead) fun read(address: Int, struct: Struct, bytesToRead: Int = struct.size()) = read(address.toLong(), struct, bytesToRead) fun read(address: Long, bytesToRead: Int): Memory = TODO() fun read(address: Int, bytesToRead: Int) = read(address.toLong(), bytesToRead) fun byte(address: Long, offset: Long = 0) = read(address, 1).getByte(offset) fun byte(address: Int, offset: Long = 0) = byte(address.toLong(), offset) fun short(address: Long, offset: Long = 0) = read(address, 2).getShort(offset) fun short(address: Int, offset: Long = 0) = short(address.toLong(), offset) fun char(address: Long, offset: Long = 0) = read(address, 2).getChar(offset) fun char(address: Int, offset: Long = 0) = char(address.toLong(), offset) fun int(address: Long, offset: Long = 0) = read(address, 4).getInt(offset) fun int(address: Int, offset: Long = 0) = int(address.toLong(), offset) fun long(address: Long, offset: Long = 0) = read(address, 8).getLong(offset) fun long(address: Int, offset: Long = 0) = long(address.toLong(), offset) fun float(address: Long, offset: Long = 0) = read(address, 4).getFloat(offset) fun float(address: Int, offset: Long = 0) = float(address.toLong(), offset) fun double(address: Long, offset: Long = 0) = read(address, 8).getDouble(offset) fun double(address: Int, offset: Long = 0) = double(address.toLong(), offset) fun boolean(address: Long, offset: Long = 0) = byte(address, offset).unsign() > 0 fun boolean(address: Int, offset: Long = 0) = boolean(address.toLong(), offset) fun write(address: Long, data: Pointer, bytesToWrite: Int) fun write(address: Int, data: Pointer, bytesToWrite: Int) = write(address.toLong(), data, bytesToWrite) fun write(address: Long, data: Memory, bytesToWrite: Int = data.size().toInt()) = write(address, data as Pointer, bytesToWrite) fun write(address: Int, data: Memory, bytesToWrite: Int = data.size().toInt()) = write(address.toLong(), data, bytesToWrite) fun write(address: Long, struct: Struct, bytesToWrite: Int = struct.size()) = write(address, struct.pointer, bytesToWrite) fun write(address: Int, struct: Struct, bytesToWrite: Int = struct.size()) = write(address.toLong(), struct, bytesToWrite) // ... } 

Esta API funciona con Long for address , pero también acepta Int por alguna razón. Creo que deberías ver uno (ei Long ) y dejar que el consumidor se preocupe por convertir Int a Long . Esto no es responsabilidad de una API. Además, si un consumidor trabaja con una API que usa Long para la address , generalmente usará Long para manipular las direcciones de su lado también. Esto simplifica la API y ahorra en las conversiones Int a Long y Back, lo que mejora el performance.