Kotlin 是否有一种优雅的方式将可空类型分配给可选参数?

Kotlin 是否有一种优雅的方式将可空类型分配给可选参数?,kotlin,Kotlin,我有以下功能: fun leftPad(value: String, length: Int = 3, char: Char = ' '): String = value.padStart(length, char) 是否有一种方法可以调用此函数并将类型为null的值传递给可选参数,如中所示: length: Int? = getLength() char: Char? = getChar() leftPad(value, length = length, char = char) 我尝试过

我有以下功能:

fun leftPad(value: String, length: Int = 3, char: Char = ' '): String = value.padStart(length, char)
是否有一种方法可以调用此函数并将类型为null的值传递给可选参数,如中所示:

length: Int? = getLength()
char: Char? = getChar()
leftPad(value, length = length, char = char)
我尝试过的唯一解决方法是:

fun leftPad(value: String, length: Int? = null, char: Char? = null): String {
        val length = length ?: 4
        val char = char ?: ' '
        return value.padStart(length, char)
    }

它符合我的要求,但是名称shadowed warning让我有点不舒服。

名称shadowed warning只是说您的
val length
在方法中隐藏
length
参数。要消除它,可以内联默认值或重命名局部变量。例如:

fun leftPad(value: String, length: Int? = null, char: Char? = null): String {
    return value.padStart(length ?: 4, char ?: ' ')
}


shadowed警告的名称只是表示您的
val length
对方法中的
length
参数进行了阴影处理。要消除它,可以内联默认值或重命名局部变量。例如:

fun leftPad(value: String, length: Int? = null, char: Char? = null): String {
    return value.padStart(length ?: 4, char ?: ' ')
}


这取决于你对优雅的定义,但也有可能通过反射来实现

下面是一种(
construct
)将参数映射应用到主构造函数的方法,以及第二种(
constructNullIsDefault
)方法,该方法在应用映射之前过滤掉
null
值(以及一些带有
对的vararg的语法糖,以避免每次调用都必须自己构建映射)

nullisdefault(vararg参数:Pair):X?{
返回构造(arguments.toMap().filterValues{it!=null}作为映射)
}
内联有趣构造(参数:Map):X?{
val klass=X::class
val constructor=klass.primaryConstructor!!
val parameters=constructor.parameters
val参数映射=
arguments.map{argument->parameters.find{it.name==argument.key}!!到argument.value}.toMap()
返回构造函数.callBy(parameterMap)
}
@试验
有趣的测试{
val x=“你好”
val y=null作为字符串?
val abc=constructNullIsDefault(“x”到x,“y”到y)
println(abc)
}

这取决于你对优雅的定义,但也可以通过反射来实现

下面是一种(
construct
)将参数映射应用到主构造函数的方法,以及第二种(
constructNullIsDefault
)方法,该方法在应用映射之前过滤掉
null
值(以及一些带有
对的vararg的语法糖,以避免每次调用都必须自己构建映射)

nullisdefault(vararg参数:Pair):X?{
返回构造(arguments.toMap().filterValues{it!=null}作为映射)
}
内联有趣构造(参数:Map):X?{
val klass=X::class
val constructor=klass.primaryConstructor!!
val parameters=constructor.parameters
val参数映射=
arguments.map{argument->parameters.find{it.name==argument.key}!!到argument.value}.toMap()
返回构造函数.callBy(parameterMap)
}
@试验
有趣的测试{
val x=“你好”
val y=null作为字符串?
val abc=constructNullIsDefault(“x”到x,“y”到y)
println(abc)
}

目前,没有办法告诉编译器执行您想要的操作。您可以传递任何内容作为参数的值,然后在调用过程中不计算默认值,或者不传递参数,然后计算默认值。目前,您的变通方法似乎是实现这一点的最佳方法。目前,没有办法告诉编译器执行您想要的操作。您可以传递任何内容作为参数的值,然后在调用过程中不计算默认值,或者不传递参数,然后计算默认值。目前,您的变通方法似乎是最好的解决方法。
inline fun <reified X : Any> constructNullIsDefault(vararg arguments: Pair<String, Any?>): X? {
    return construct(arguments.toMap().filterValues { it != null } as Map<String, Any>)
}

inline fun <reified X : Any> construct(arguments: Map<String, Any>): X? {
    val klass = X::class
    val constructor = klass.primaryConstructor!!
    val parameters = constructor.parameters
    val parameterMap =
        arguments.map { argument -> parameters.find { it.name == argument.key }!! to argument.value }.toMap()
    return constructor.callBy(parameterMap)
}

@Test
fun testAbc() {
    val x = "hello"
    val y = null as String?

    val abc = constructNullIsDefault<Abc>("x" to x, "y" to y)
    println(abc)
}