如何区分显式null和省略参数

时间:2018-06-05 08:02:30

标签: kotlin

我想实现这样的目标,基本上将省略的参数与显式设置为null区别开来:

sealed class Expr
data class HasValue<out T>(val value: T)
object IsNull: Expr()

/* inside a class */
fun filter(v1: Expr<Int>? = null, v2: Expr<String>? = null): Collection<T> {
    when (v1) {
        is HasValue -> /* Filter collection elements that have some attr set to given value */
        is IsNull -> /* filter collection elements that have some attr set to null */
        is null -> /* do nothing, return all elements */
    }

    when (v2) /* so on */
}

/* call site */
myObj.filter(v1=IsNull<Int>(), v2=HasValue<String>("string"))

修改

工作解决方案:

sealed class Expr<out T> {
    abstract val value: T?
}
data class WithValue<out T>(override val value: T?) : Expr<T>()

/* usage */
fun filter(v1: Expr<Int>? = null) {
    when (v1) {
        is WithValue -> println(if ((v1.value ?: 0) > 10) "10 and above" else "less") /* Type safe, explicit null handling */
        null -> println("isNull") /* parameter was omitted */
    }
}
filter(WithValue<Int>(null)) /* will match explicit null elements */
filter() /* will ignore v1 from filtering */

2 个答案:

答案 0 :(得分:0)

你可以做什么,而不是使用null,而是使用自定义私有实例,如:

/* inside a class */
private val EMPTY = Expr()
fun filter(v1: Expr<Int>? = EMPTY, v2: Expr<String>? = EMPTY): Collection<T> {
    if (v1 === EMPTY) {
        // parameter not defined by user
    } else {
        // parameter defined by user
    }
}

答案 1 :(得分:0)

提供的代码存在一些问题,主要是泛型。但我认为问题的主要内容是详尽when 。如果你想按类型匹配,你可以写

  • is SomeClass用于课程
  • Object对象
  • null for null

所以你的when应该是这样的:

when (v1) {
    is HasValue<*> -> /* Filter collection elements that have some attr set to given value */
    IsNull -> /* filter collection elements that have some attr set to null */
    null -> /* do nothing, return all elements */
}

和整个代码:

sealed class Expr {
    data class HasValue<out T>(val value: T) : Expr()
    object IsNull: Expr()
}

private fun <T> filter(v1: Expr? = null, v2: Expr? = null): Collection<T> {
    when (v1) {
        is HasValue<*> -> /* Filter collection elements that have some attr set to given value */
        IsNull -> /* filter collection elements that have some attr set to null */
        null -> /* do nothing, return all elements */
    }
    // matching with v2
}

/* call site */
filter<Int>(v1=IsNull, v2=HasValue("string"))