Kotlin:有没有办法清理数字过载?

时间:2016-07-24 06:05:11

标签: numbers type-conversion kotlin data-conversion

我常常发现自己为数字类型创建了大量重载,因为Kotlin并没有为非文字进行隐式转换。这导致了大量的重复过载功能,即吨和吨的样板。

我在这里可以看到一个痛苦的例子:https://github.com/Jire/Arrowhead/blob/master/src/main/kotlin/org/jire/arrowhead/Source.kt

我理解隐式转换可能导致错误的原因,但我认为在大多数情况下,特别是对于"放大"像Byte -> IntInt -> Long这样的转化,数据不会丢失,应该有更好的方法。

所以......我的问题是你如何应对这个问题?有没有创造性的方法来解决这个问题?

1 个答案:

答案 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并节省了LongInt和后退转化,从而提高了效果。