对于一些变量,如果我们要在后面才对它进行复制,那么我们就要在前面给他初始化为空
class MainActivity : AppCompatActivity(), View.OnClickListener{
private var adapter: MsgAdapter? =null
override fun onCreate(savedInstanceState: Bundle?) {
…
//判断是否被初始化
if(!::adapter.isInitialized) {
adapter = MsgAdapter(msgList)
}
…
}
并且在使用使还要进行判空操作
override fun onClick(v: View?) {
…
adapter?.notifyItemInserted(msgList.size - 1)
…
}
延迟初始化使用的是lateinit关键字,它可以告诉Kotlin编译器,我会在晚些时候对这个变量进行初始化,这样就不用在一开始的时候将它赋值为null了,在后面也可以直接调用。
class MainActivity : AppCompatActivity(), View.OnClickListener {
private lateinit var adapter: MsgAdapter
override fun onCreate(savedInstanceState: Bundle?) {
…
adapter = MsgAdapter(msgList)
…
}
override fun onClick(v: View?) {
…
adapter.notifyItemInserted(msgList.size - 1)
…
}
}
同时我们还可以用下面操作判断是否初始化
if(!::adapter.isInitialized) {
adapter = MsgAdapter(msgList)
}
首先我们定义一个Result接口,用Success和Failure实现Result,用于处理成功的结果和失败的结果
interface Result
class Success(val msg: String) : Result()
class Failure(val error: Exception) : Result()
接下来再定义getResultMsg()方法接受一个Result参数,我们通过when语句来判断:如果Result属于Success,就返回成功的消息,如果Result属于Failure,就返回失败的消息
fun getResultMsg(result: Result) = when (result) {
is Success -> result.msg
is Failure -> "Error is ${result.error.message}"
else -> throw IllegalArgumentException()
}
到目前为止,代码都是没有问题的,但比较讨厌的是,接下来我们不得不再编写一个else条件,否则Kotlin编译器会认为这里缺少条件分支,代码将无法通过编译。
另外,编写else条件还有一个潜在的危险。如果我们新增一个UnKnow类并实现Result接口,用于表示未知的处理结果,但忘记再getResultMsg()方法中添加相应的条件分支,这个时候编译器是不会提醒我们的,而是会在运行的时候进入else分支,从而判处异常导致程序崩溃。
而使用密封类优化代码,就可以保证Kotlin编译器会自动检查该密封类有哪些子类,并强制要求你将每一个子类所对应的条件全部处理,且即使没有编写else条件,也不可能会出现漏写条件分支的情况。
//定义密封类
sealed class Result
class Success(val msg: String) : Result()
class Failure(val error: Exception) : Result()
fun getResultMsg(result: Result) = when (result) {
is Success -> result.msg
is Failure -> "Error is ${result.error.message}"
}