我有一个函数:
object CliUtils {
var skipOptionalArgs = false
fun readOptional(variableName: String, defaultValue: String? = null): String? {
if (skipOptionalArgs) return defaultValue
print("Provide the $variableName (optional${if (defaultValue != null) ", default: $defaultValue" else ""}): ")
return readln().takeIf { it.isNotEmpty() } ?: defaultValue
}
}
当我像这样使用这个函数时…
val inputName = readOptional("input name", "Input")
inputName
的类型是String?
。由于我给出的"Input"
的defaultValue
,我知道变量不是null
。
我可以用一个双感叹号,像这样:
val inputName = readOptional("input name", "Input")!!
但是我觉得应该有一种方法来定义readOptional
函数,这样就可以推断出String的返回类型,而不需要使用双感叹号。我想到了契约,但据我所知,契约只能引用参数,而不能引用返回类型。我还想到了将defaultValue
参数类型的类型链接到返回类型的泛型,但我无法让它与其空性一起工作。
有没有办法让Kotlin明白如果defaultValue != null
返回值也不是null?
3条答案
按热度按时间xdnvmnnf1#
你可以使用泛型来实现,但为了安全起见,我认为你必须为空默认版本提供一个重载。
x6h2sr282#
这是可能的泛型:
调用方不再需要邪恶的
!!
检查:但我们必须付出的代价是未经检查的演员阵容。这是因为编译器无法确保方法在每个条件下都返回非空默认参数。
因此,我们让调用者站点可以轻松地使用所有变体,而无需额外的检查。但是正如前面提到的,编译器不能阻止我们错误地使用它。仍然不可能额外设置(错误的)泛型类型,或者让它从瓦尔类型推断错误的类型:
编辑:也可以结合一个额外的方法重载来解决,如@Tenfour04提到的:
我的想法和更多的解释也可以在这里找到:Kotlin generics with nullable types
vawmfj5a3#
另一个选项是重载函数: