Kotlin - 返回当前实例的类型

时间:2018-02-15 13:35:20

标签: kotlin

我正在Kotlin建立一个验证库。基类是abstract并实现适用于所有类型的方法;例如isNotNull

abstract class Validator<V>(protected val value: V?) {
    fun isNotNull(): Validator<V> {
        if(value == null) {
            // ... some validation handling here ...
        }

        return this
    }
}

然后我对特定类型的验证器进行子类化:

class IntValidator(value: Int?) : Validator<Int>(value) {
    fun isNotZero(): IntValidator {
        if(value == 0) {
            // ... some validation handling here ...
        }

        return this
    }
}

现在说我要验证一个Int?不为空且不为零

val validator = IntValidator(myNullableInteger)

validator
    .isNotNull()
    .isNotZero()

上述代码不起作用,因为.isNotNull()返回Validator<V>而不是IntValidator,因此.isNotZero()不再在范围内。

方法有没有办法返回实例化它们的类型(在我的例子中,我希望它返回IntValidator,而不是Validator<T>)?

3 个答案:

答案 0 :(得分:2)

单向,但未经检查的演员:

fun main(args: Array<String>) {
  val validator = IntValidator(2)

  validator
    .isNotNull()
    .isNotZero()
}

abstract class Validator<V, out R>(protected val value: V?) {
    open fun isNotNull(): R {
        if(value == null) {
            // ... some validation handling here ...
        }

        return this as R
    }
}

class IntValidator(value: Int?) : Validator<Int, IntValidator>(value) {
    fun isNotZero(): IntValidator {
        if(value == 0) {
            // ... some validation handling here ...
        }

        return this
    }
}

答案 1 :(得分:2)

也许您应该重新考虑API设计。那么不是链接方法和使用范围函数呢?

val validator = IntValidator(myNullableInteger)
with(validator) {
    isNotNull()
    isNotZero()
}

IntValidator的范围内,两种方法都可以访问。

答案 2 :(得分:2)

this kotlinlang thread所述,您可以使用扩展方法:

abstract class Validator<V>(internal val value: V?)
fun <T: Validator<U>, U> T.isNotNull(): T {
    if(this.value == null) {
        // ... some validation handling here ...
    }
    return this
}

class IntValidator(value: Int?) : Validator<Int>(value)

@Suppress("FINAL_UPPER_BOUND")
fun <T: IntValidator> T.isNotZero(): T {
    if (this.value == 0) {
        // ... some validation handling here ...
    }
    return this
}

fun main() {
    val validator = IntValidator(0)
    validator
            .isNotNull()
            .isNotZero()
}

这使您可以将对象类型用作函数的泛型参数,这意味着您也可以接收对象类型作为结果。通用边界允许您在返回调用实例的类型时使用类型安全。