Kotlin使用Lambda作为初始化程序

Rar*_*ima 2 readability initialization properties kotlin

所以我有以下困境。这不是关于什么不起作用的问题,而是关于什么将是更优雅/更好的实践以及为什么的问题。

因此,我们知道邻接init块,初始化逻辑进入其中。也许您打开文件或从配置文件中读取一些常量,也许您基于使用构造函数参数的更复杂算法来设置一些属性。

但是,如果您的某些属性确实需要一些逻辑,琐碎的逻辑,例如验证参数或类似的东西,该怎么办?而且此逻辑仅与该特定属性有关,而与其他属性没有交互?

例如:

class MyCircularQueue(k: Int) {

    private val arr = { 
        if (k < 1) 
            throw IllegalArgumentException("k must be at least 1") 
        else  
            Array(k) { 0 }
    }()

    private var head = 0
    private var tail = 0
    private var empty = true

}
Run Code Online (Sandbox Code Playgroud)

这里arr需要初始化为0s 的数组,但如果k小于1 则显然存在问题。需要非常短的初始化逻辑,只需简单的检查即可引发异常或初始化数组。没有与其他属性的交互,没有复杂的逻辑,只是极其琐碎的检查或逻辑。

在这种情况下,我想知道将琐碎的初始化逻辑放在“临时”代码块(当场调用的lambda)中是否更好。这样做的好处是,声明和初始化逻辑将在同一位置,不需要时就不会分开,我认为这样更易读。

因此,在我写完这篇文章之后,我想知道是否还有其他人对于非常简单的初始化逻辑有此问题,但是我真的找不到任何相关信息。

底线是:可以吗?是好的做法,还是至少不是坏的做法?是否有意义?在Kotlin中,有没有更好的和/或官方的方法来做到这一点?

s1m*_*nw1 5

函数变通方法不是必需的,它if是一个表达式并返回一个值,因此可以简化:

private val arr =
    if (k < 1)
        throw IllegalArgumentException("k must be at least 1")
    else
        Array(k) { 0 }
Run Code Online (Sandbox Code Playgroud)

另外,Kotlin在标准库中带有很多功能性API,可以帮助创建简洁的衬纸。在这种情况下,您可以执行以下操作:

private val arr =
     k.takeIf { it > 0 }?.let { Array(k) { 0 } } ?: throw IllegalArgumentException("k must be at least 1")
Run Code Online (Sandbox Code Playgroud)