简体   繁体   English

排列 <Number> :获取并设置Int值而不进行强制转换

[英]Array<Number>: get and set Int values without casting

I am building a Matrix class and want to be able to store Number s in a 2d Array. 我正在构建一个Matrix类,并希望能够将Number存储在二维数组中。

var data: Array<Array<Number>> = Array(width, {Array(height, {0})})

This does not work because Array<Number> and Array<Int> are invariant. 这不起作用,因为Array<Number>Array<Int>是不变的。 I can make it work by using Array<Array<out Number>> , but the Matrix will be immutable, and I don't want that... 我可以通过使用Array<Array<out Number>>来使它工作,但Matrix将是不可变的,我不希望这样......

Casting {0 as Int} makes the compiler error go away, but this does not seem like a good idea. {0 as Int}会使编译器错误消失,但这似乎不是一个好主意。 I also want to do things like addition and I noticed that it's not possible to add Number s: 我也想做像添加这样的事情,我注意到它不可能添加Number s:

var n: Number = 1
n + 1 // does not work

So how could I solve this problem? 那么我怎么能解决这个问题呢? And why exactly can I not add two Number s? 为什么我不能添加两个Number

Number is an abstract class and does not define anything for addition. Number是一个抽象类,不会为添加定义任何内容。 And since there's no defined method for adding the numbers, you can't do numberInstane + otherNumberInstance . 由于没有用于添加数字的已定义方法,因此您无法执行numberInstane + otherNumberInstance You can, however, create an operator function for it: 但是,您可以为它创建一个运算符函数:

infix operator fun Number.plus(other: Number) : Number{
    return when (this) {
        is Double -> this + other.toDouble()
        is Int -> this + other.toInt()
        is Long -> this + other.toLong()
        is Float -> this + other.toFloat()
        is Short -> this + other.toShort()
        is Byte ->  this + other.toByte()
        else -> 0
    }
}

Note that this only applies to addition. 请注意,这仅适用于添加。 The rest of the functions would follow the same pattern, but replacing the operator (here it's + ) and the name of the function (here it's plus ). 其余的函数将遵循相同的模式,但替换运算符(这里是+ )和函数的名称(这里是plus )。


As mer msrd0's comment, the above would result in 1 + 1.5 being 2, because it rounds down. 作为mer msrd0的评论,上面会导致1 + 1.5为2,因为它向下舍入。 Kotlin supports adding number types across each other, which ends up with this slightly horrid solution: Kotlin支持在彼此之间添加数字类型,最终得到了这个有点可怕的解决方案:

infix operator fun Number.plus(other: Number) : Number{

    when {
        this is Double -> {
            return when(other){
                is Double -> this + other
                is Int -> this + other
                is Long -> this + other
                is Float -> this + other
                is Short -> this + other
                is Byte ->  this + other
                else -> 0
            }
        }
        this is Int -> {
            return when(other){
                is Double -> this + other
                is Int -> this + other
                is Long -> this + other
                is Float -> this + other
                is Short -> this + other
                is Byte ->  this + other
                else -> 0
            }
        }
        this is Long -> {
            return when(other){
                is Double -> this + other
                is Int -> this + other
                is Long -> this + other
                is Float -> this + other
                is Short -> this + other
                is Byte ->  this + other
                else -> 0
            }
        }
        this is Float -> {
            return when(other){
                is Double -> this + other
                is Int -> this + other
                is Long -> this + other
                is Float -> this + other
                is Short -> this + other
                is Byte ->  this + other
                else -> 0
            }
        }
        this is Short -> {
            return when(other){
                is Double -> this + other
                is Int -> this + other
                is Long -> this + other
                is Float -> this + other
                is Short -> this + other
                is Byte ->  this + other
                else -> 0
            }
        }
        this is Byte -> {
            return when(other){
                is Double -> this + other
                is Int -> this + other
                is Long -> this + other
                is Float -> this + other
                is Short -> this + other
                is Byte ->  this + other
                else -> 0
            }
        }
        else -> return 0
    }
}

The nested when-statement helps autocasting the values, which is necessary since Number isn't a specific known class. 嵌套的when语句有助于自动更新值,这是必需的,因为Number不是特定的已知类。 There might be a better solution though, but without knowing the specific type. 可能有更好的解决方案,但不知道具体的类型。 The extension function is mostly just auto-casting based on the type, but there can't be a single variable because it would need to be defined as a Number to accept all the types, and since there are two vars where both need proper casting based on the passed type, it ends up being slightly messy. 扩展函数大多只是基于类型的自动转换,但是不能有单个变量,因为它需要被定义为一个数字来接受所有类型,并且因为有两个vars都需要适当的转换根据传递的类型,它最终会有点凌乱。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM