Kotlin 我应该在声明、init块、构造函数或lateinit上初始化变量吗?
我想知道kotlin中初始化变量的4种方法(我知道)和哪一种方法最受欢迎有什么区别 首先,在声明时初始化它:Kotlin 我应该在声明、init块、构造函数或lateinit上初始化变量吗?,kotlin,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 = "Hello world"
}
其次,在init块上初始化它:
class MyClass {
var textString: String
init {
textString = "Hello world"
}
}
第三,使用构造函数:
class MyClass {
var textString : String
constructor() {
this.textString = "Hello world"
}
}
class Foo(var bar: String = "default value")
第四,lateinit:
class MyClass {
lateinit var textString : String
fun initializeVariable() { //Assume this is called by something
this.textString = "Hello world"
}
}
我主要是寻找编译时间和总体“良好实践”的差异。我知道您可以使用一些“技巧”,比如使用init块初始化一些变量,这些变量总是相同的,不管使用的构造函数是什么,但这是合适的方法吗?
lateinit
不相关,因为它不初始化任何东西
同一行上的初始化仅适用于简单属性。您可以使用闭包,然后调用它们,就像这样vali={//complex code}()
,但这很难看
有关构造函数vs
init
块的详细讨论,请参阅。理解初始化顺序的最简单方法是创建一个包含主、次和init
块的类,然后使用println
或简单地使用调试器跟踪执行。从技术角度看,没有太大区别,至少就简单属性而言,如示例中所示,该属性无论如何都会初始化
lateinit
修饰符在这里是一个小小的例外-它允许延迟初始化:就像说“我现在不能设置有意义的值,但我确信它将在第一次使用之前设置”。它在Kotlin-Spring框架集成中很有用,因为某些原因不想/不能使用构造函数注入,并且允许属性注入
@Autowired lateinit var foo: Foo
或者在使用Spring的@值时
@Value("\#{props.foo}") lateinit var foo: String
不过,从读者/维护者的角度来看,这是有区别的,当您需要一些额外的功能时,比如说前提条件验证。根据经验,尽早初始化属性:首选方法是在主构造函数中:
class MyClass {
var textString : String
constructor() {
this.textString = "Hello world"
}
}
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字符串属性不能为空:
class Foo(var bar: String = "default") {
init {
require(bar.isNotBlank()) { "Bar cannot be blank" }
}
}
在可能的情况下,我会使用构造函数初始化
另外,如果你愿意花几美元买一本关于Kotlin良好实践和模式的书,我强烈推荐Marin Moskała的有效Kotlin有多种方法,因为有多种需求,因此没有适合所有人的方法,所以我投票以基于意见的方式结束这个问题。“我想知道初始化变量的4种方法之间有什么区别”我不认为这是基于观点的。最理想的解决方案是什么“我同意这听起来是基于观点的,但这是因为我的措辞不当。我的意思是我想在哪里使用每一个,以及为什么这一个会比其他的好。如果你把一个字段设置为一个已知的常数,最好的方法就是选择1。如果需要使用构造函数参数,请使用constructor/init。当您说lateinit
在Kotlin的早期很有用,你是在暗示它不再有用了吗?@Tenfour04它对于属性注入或在构造过程中无法初始化某些东西时仍然有用-例如在android中,你等待平台调用onCreate
,因为这是你可以引用应用程序资源的第一个点。@Pawel这就是我的意思。我已经澄清了答案,正如@Pawel提到的,当通过属性而不是构造函数使用依赖注入时,这仍然很有用。