为Nullable扩展函数

610 阅读2分钟

如果想给函数扩展一个+操作符,非常简单,举个例子:

data class Vector(val x: Int, val y: Int) {
    operator fun plus(other: Vector): Vector {
        return Vector(x + other.x, y + other.y)
    }
}

fun main() {
    println(Vector(2, 4) + Vector(5, 6))
}

输出:

Vector(x=7, y=10)

我们定义了一个data class,这个类包含一个+操作符的重定义,使它可以支持两个Vector相加的情况。输出结果,与我们预想的一样,那么,如何支持Nullable的对象呢?

非常简单:

data class Vector(val x: Int, val y: Int) {
    operator fun plus(other: Vector?): Vector {
        return Vector(x + (other?.x ?: 0), y + (other?.y ?: 0))
    }
}

fun main() {
    println(Vector(2, 4) + null)
}

输出:

Vector(x=2, y=4)

我们修改了函数plus的实现,使之支持Nullable对象。

但是,如果null+左边,而不是在右边,事情就没有那么简单了。

fun main() {
    println(null + Vector(2, 4))
}

输出:

nullVector(x=2, y=4)

输出竟然多了个null,其实当我们在编译器中,鼠标靠近+操作符的时候,我们能够看到这样的提示:

图片.png

它重载的是String类的操作符,导致在解析null的时候,用的是字符串的null,所以这种情况下,并没有使用我们定义的plus函数。

如果我们想支持null+左边,就需要这样写:

operator fun Vector?.plus(other: Vector): Vector {
    return Vector(other.x + (this?.x ?: 0), other.y + (this?.y ?: 0))
}

此时,当我们运行null + Vector(2, 4)时,将会得到正确的结果。

完整代码如下:

data class Vector(val x: Int, val y: Int) {
    operator fun plus(other: Vector?): Vector {
        return Vector(x + (other?.x ?: 0), y + (other?.y ?: 0))
    }
}

operator fun Vector?.plus(other: Vector): Vector {
    return Vector(other.x + (this?.x ?: 0), other.y + (this?.y ?: 0))
}

fun main() {
    println(Vector(2, 4) + Vector(5, 6))
    println(Vector(2, 4) + null)
    println(null + Vector(2, 4))
}

输出:

Vector(x=7, y=10)
Vector(x=2, y=4)
Vector(x=2, y=4)

非常灵巧,不是吗?