我经常发现自己为数字类型创建了很多重载,因为Kotlin不会对非文字进行隐式转换。这导致大量重复的过载功能,即成千上万的样板。
我在此遇到的痛苦的一个例子可以在这里看到:https://github.com/Jire/Arrowhead/blob/master/src/main/kotlin/org/jire/arrowhead/Source.kt
我理解隐式转换会导致bug的原因,但是我认为在大多数情况下,尤其是对于不丢失数据的Byte -> Int
和Int -> Long
之类的“扩大”转换,应该有更好的方法。
所以...我的问题是您如何处理?有什么创造性的方法可以解决这个问题?
最佳答案
回答您的问题:可以将通用函数与 Number
一起使用。然后它将接受Number
的任何子类型。然后,您可以将值转换为任何其他数字类型:
fun boo(x: Number) {
val y = x.toLong()
println(y is Long)
}
唯一的缺点是自动装箱,但这与您的情况无关。
关于您发布的代码:我相信您有一些架构错误会导致这种情况。这是您的API,没有太多详细信息:
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)
// ...
}
此API与
Long
一起用于address
,但由于某种原因也接受Int
。我认为您应该偷看一个(例如Long
),让消费者担心将Int
转换为Long
。这不是API的责任。此外,如果消费者使用将Long
用作address
的API,那么他通常也将使用Long
来处理自己身边的地址。这简化了API,并节省了Int
到Long
以及向后转换的时间,从而提高了性能。
关于numbers - Kotlin:有没有办法清除数字重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38549247/