generics - kotlin - 删除类属性中的可为空性

标签 generics kotlin nullable non-nullable kotlin-contracts

我有一个带有一些可为空属性的类

data class RequestModel(
    val description: String?
)

和验证函数

fun validate(model: RequestModel): RequestModel{
    if(model.description == null) throw IllegalArgumentException("description must be non null")
    return model
}

在此验证步骤之后,我需要一种方法来指示 description 属性的不可空性。

一个解决方案是创建一个具有非 null 属性的新数据类 data class RequestModel(val description: String)
但我正在寻找一种通用方法来避免创建每个用例新类。

理想的通用解决方案:

fun validate(model: RequestModel): NoNullableField<RequestModel>

如何以通用方式从具有可为 null 属性的类的属性中删除可为 null 性?使用某种 kotlin 编译器合约有用吗?

最佳答案

您可以使用Kotlin reflection获取所有属性并检查它们是否不为空:

inline fun <reified T : Any> T.requireNoNullableProperties() = NoNullableProperties(this, T::class)

class NoNullableProperties<out T : Any>(val obj: T, clazz: KClass<T>) {
    init {
        clazz.memberProperties.forEach { prop ->
            if (prop.returnType.isMarkedNullable) {
                prop.isAccessible = true
                requireNotNull(prop.get(obj)) {
                    "${prop.name} must be not null, obj - [$obj]"
                }
            }
        }
    }

    operator fun <R> get(property: KProperty1<in T, R?>): R = requireNotNull(property.get(obj)) {
        "Extension and mutable properties can't be validated, property - [$property], obj - [$obj]"
    }
}

用例:

val validated = model.requireNoNullableProperties()
val description: String = validated[RequestModel::description]

此外,您还可以提取 validated[RequestModel::description]NoNullableProperties<RequestModel> 的扩展属性:

val ValidRequestModel.description get() = get(RequestModel::description)

哪里ValidRequestModel是:

typealias ValidRequestModel = NoNullableProperties<RequestModel>

用例:

val validated = model.requireNoNullableProperties()
val description: String = validated.description

关于generics - kotlin - 删除类属性中的可为空性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59015821/

相关文章:

java - 为什么这个赋值在 Java 泛型中是非法的?

android - 有没有办法在 Espresso 测试期间暂停和恢复 Activity ?

kotlin - 如何将编码更改为下载的文件Kotlin

c# - 如何在数据访问层 (C#) 中表示空值

c# - 如何在 C# 中将泛型对象分配给非泛型引用

c# - 将泛型类型参数限制为 System.Enum

android - 调用 HTTP 请求时,Toast 未显示在登录流程中

c# - 为什么接受引用类型的泛型方法不接受可空类型作为参数?

C# 我应该在这里投什么类型?

c# - 当泛型不匹配时,为什么泛型方法不能选择特定方法?