Kotlin 在本例中,如何限制可变性的风险?

Kotlin 在本例中,如何限制可变性的风险?,kotlin,immutability,Kotlin,Immutability,我的代码类似于: fun验证(问题,答案){ val错误:MutableList=mutableListOf() 如果(!条件_1){ 错误。添加(“条件_1未验证”) } 如果(!条件_2){ 错误。添加(“条件2未验证”) } 返回错误 } 这里的错误是一个可变列表。我正试图重写限制可变性的程序 第一种方法是: errorsImmutable=errors.toList() 并返回不可变列表errorsImmutable,以防止从外部对其进行修改 另一个解决方案是: fun验证(问题,答

我的代码类似于:

fun验证(问题,答案){
val错误:MutableList=mutableListOf()
如果(!条件_1){
错误。添加(“条件_1未验证”)
}
如果(!条件_2){
错误。添加(“条件2未验证”)
}
返回错误
}
这里的
错误
是一个可变列表。我正试图重写限制可变性的程序

第一种方法是:

errorsImmutable=errors.toList()
并返回不可变列表
errorsImmutable
,以防止从外部对其进行修改

另一个解决方案是:

fun验证(问题,答案){
val错误:List=emptyList()
如果(!条件_1){
val mutableList=errorLogs.toMutableList()
可变列表。添加(“条件_1未验证”)
errors=mutableList.toList()
}
如果(!条件_2){
val mutableList=errorLogs.toMutableList()
可变列表。添加(“条件2未验证”)
errors=mutableList.toList()
}
返回错误
}

哪一个更好。一般来说,还有更好的方法吗?

您忽略了在示例中显示函数的返回类型。通常认为只返回只读列表并相信使用者不会将其强制转换为可变列表来修改它是可以的

fun verify(): List<String> {
    val errors: MutableList<String> = mutableListOf()
    if (!condiditon_1) {
        errors.add("Condition_1 is not verified")
    }
    if (!condition_2) {
        errors.add("Condition_2 is not verified")
    }
    return errors
}
fun verify():列表{
val错误:MutableList=mutableListOf()
如果(!条件_1){
错误。添加(“条件_1未验证”)
}
如果(!条件_2){
错误。添加(“条件2未验证”)
}
返回错误
}

没有一种干净的方法可以创建一个真正不可变的列表,而不编写自己的不可变列表类。请注意,标准库的
listOf
函数返回只读列表,而不是不可变列表,只有一个元素参数的重载除外。

一般来说,如果您可以创建一个已填充的集合,这往往比创建一个空集合然后填充它要好——原因有很多,包括你所说的不变性。当然,这并不总是可能的(或优雅的),但在这种情况下,有一种方法:

fun verify() = listOfNotNull(
    if (condition1) "Condition1 is not verified" else null,
    if (condition2) "Condition2 is not verified" else null,
)
或同等标准:

fun verify() = listOfNotNull(
    "Condition1 is not verified".takeIf{ condition1 },
    "Condition2 is not verified".takeIf{ condition2 },
)
这样,您就永远看不到列表的可变引用(尽管在
listOfNotNull()
实现中可能涉及到该引用)。而且由于列表现在是一个表达式,您可以使用表达式体函数,并让它推断类型(当然,较短的代码并不总是更简单、更清晰或更易于维护,但在这里,我认为可能是这样的——当然,这取决于周围的代码。无论如何,这通常是一个有用的学习练习。)

这里有一种更具声明性的方法,它分别定义了条件(并考虑了通用消息格式):

另外,我错过了另一个调整:如果您使用而不是显式指定
Pair
,它的可读性可能会稍高一些:

val conditions = listOf(
    { condition1 } to "Condition1",
    { condition2 } to "Condition2",
)
val conditions = listOf(
    { condition1 } to "Condition1",
    { condition2 } to "Condition2",
)