3

NumberMatrix クラスを作成していて、s を 2 次元配列に格納できるようにしたいと考えています。

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

Array<Number>Array<Int>は不変であるため、これは機能しません。を使用して機能させることはできますArray<Array<out Number>>が、マトリックスは不変になり、それは望ましくありません...

キャスト{0 as Int}によりコンパイラ エラーは解消されますが、これは良い考えとは思えません。また、足し算のようなこともしたいのですが、 Numbersを追加できないことに気付きました。

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

では、どうすればこの問題を解決できますか? Numberそして、正確に 2 つの sを追加できないのはなぜですか?

4

1 に答える 1

2

Number は抽象クラスであり、足し算は何も定義していません。また、数値を追加するための定義済みの方法がないため、実行できませんnumberInstane + otherNumberInstance。ただし、そのための演算子関数を作成できます。

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
    }
}

これは加算のみに適用されることに注意してください。残りの関数は同じパターンに従いますが、演算子 (ここでは+) と関数の名前 (ここでは ) を置き換えplusます。


mer msrd0 のコメントのとおり、上記は切り捨てのため、1 + 1.5 が 2 になります。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
    }
}

Number は特定の既知のクラスではないため、ネストされた when ステートメントは値の自動キャストに役立ちます。ただし、特定のタイプを知らなくても、より良い解決策があるかもしれません。拡張関数はほとんどが型に基づいて自動キャストされますが、すべての型を受け入れるには Number として定義する必要があり、両方が適切なキャストを必要とする 2 つの変数があるため、変数を 1 つにすることはできません。渡された型に基づいて、少し面倒になります。

于 2018-05-13T13:18:48.850 に答える