我常常发现自己为数字类型创建了大量重载,因为Kotlin并没有为非文字进行隐式转换。这导致了大量的重复过载功能,即吨和吨的样板。
我在这里可以看到一个痛苦的例子:https://github.com/Jire/Arrowhead/blob/master/src/main/kotlin/org/jire/arrowhead/Source.kt
我理解隐式转换可能导致错误的原因,但我认为在大多数情况下,特别是对于"放大"像Byte -> Int
和Int -> Long
这样的转化,数据不会丢失,应该有更好的方法。
所以......我的问题是你如何应对这个问题?有没有创造性的方法来解决这个问题?
答案 0 :(得分:2)
回答您的问题:您可以使用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
的{{1}},但出于某种原因也接受address
。我认为你应该偷看一个(e.i Int
)并让消费者担心将Long
转换为Int
。这不是API的责任。此外,如果消费者使用Long
Long
的API,他通常会使用address
来操纵他身边的地址。这简化了API并节省了Long
到Int
和后退转化,从而提高了效果。