kotlin - 我应该在声明、初始化块、构造函数还是后期初始化时初始化变量?
问题描述
我想知道在 kotlin 中初始化变量(我知道的)的 4 种方法之间有什么区别,哪一种是最被接受的。
首先,在声明时对其进行初始化:
class MyClass {
var textString: String = "Hello world"
}
其次,在 init 块上对其进行初始化:
class MyClass {
var textString: String
init {
textString = "Hello world"
}
}
三、使用构造函数:
class MyClass {
var textString : String
constructor() {
this.textString = "Hello world"
}
}
四、后期初始化:
class MyClass {
lateinit var textString : String
fun initializeVariable() { //Assume this is called by something
this.textString = "Hello world"
}
}
我主要是在寻找编译时间和整体“良好实践”的差异。我知道您可以使用一些“技巧”,例如使用 init 块来初始化一些始终相同的变量,而不管使用的构造函数如何,但这是否是适当的做法?
解决方案
从技术的角度来看,没有太大区别,至少在示例中的简单属性方面 - 属性无论如何都会被初始化。
修饰符在lateinit
这里有一点例外——它允许延迟初始化:就像说“我现在无法设置有意义的值,但我确信它会在第一次使用之前设置”。它在 Kotlin - Spring Framework 集成中很有用,当一个由于某种原因不想/不能使用构造函数注入时,它允许属性注入。
@Autowired lateinit var foo: Foo
或者在使用 Spring 的@Value
注解时
@Value("\#{props.foo}") lateinit var foo: String
但是,从读者/维护者的角度来看,这是有区别的,当您需要一些额外的功能时,比如前置条件验证。根据经验,尽早初始化您的属性:首选方法是在主构造函数中:
class Foo(var bar: String = "default value")
您的代码的读者,也许是未来的您,不必跳过代码来了解“默认值”的来源——它就在构造函数中!
此外,客户端代码可以在构造对象时轻松更改值,或将其保留为默认值
// set new value
val foo: Foo = Foo(bar = "specific value other than default")
// leave the default
val defaultFoo: Foo = Foo()
在类主体中初始化属性,强制客户端代码首先创建一个具有默认值的实例,然后才覆盖。
val foo = Foo()
foo.bar = "not so default"
此外,如果您想检查一些先决条件,则在主构造函数中设置值时这样做会更容易。例如 foo String 属性不能为空:
class Foo(var bar: String = "default") {
init {
require(bar.isNotBlank()) { "Bar cannot be blank" }
}
}
在可能的情况下,我会使用构造函数初始化。
另外,如果你愿意花几美元买一本关于 Kotlin 良好实践和模式的书,我强烈推荐 Marin Moskała 的Effective Kotlin https://leanpub.com/effectivekotlin