Kotlin使用技巧(2)-->延迟初始化和密封类

一、对变量延迟初始化

应用场景:如果一个类中,存在很多全局变量实例,我们不得不做许多的非空判断,即使我们非常确定他们不会为空。比如:

class MainActivity : AppCompatActivity() {
    private var recyclerAdapter: RecyclerAdapter? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        recyclerView.adapter = RecyclerAdapter(list)
        ...
    }
    override fun onClick(view:View?) {
      ...
      recyclerAdapter?.notifyDataSetChanged()
      ...
    }
}

使用lateinit关键字,他会告诉Kotlin编译器,我会在晚些时候对这个变量进行初始化,这样就不用在一开始的时候将它赋值为null了:

class MainActivity : AppCompatActivity() {
    private lateinit var recyclerAdapter: RecyclerAdapte

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        recyclerView.adapter = RecyclerAdapter(list)
        ...
    }
    override fun onClick(view:View?) {
      ...
      recyclerAdapter.notifyDataSetChanged()
      ...
    }
}

但是我们一定要注意,使用lateinit关键字一定要确保它在被调用前已经完成了和初始化工作,否则Kotlin无法保证程序的安全性。

另外,还可以通过代码来判断一个全局变量是否已经完成了初始化:

if(!::recyclerAdapter.isInitialized){
   recyclerAdapter = RecyclerAdapter(list)
}

一、使用密封类优化代码

看下面这段代码:

interface Result
class Success(val msg: String) : Result
class Fail(val error: Error) : Result

fun getResult(result: Result) = when (result) {
    is Success -> result.msg
    is Fail -> result.error.message
    else -> throw  IllegalArgumentException()
}

我们使用when语句来判断,每次都必需写else,而且如果我们新增了一个继承Result的类,但在getResult()方法中忘记添加相应的条件了,这时程序就会默认走else方法,导致崩溃。

密封类的关键字是 sealed class,用法非常简单:

sealed class Result
class Success(val msg: String) : Result()
class Fail(val error: Error) : Result

可以看到,只是将interface关键在改成了sealed class.另外密封类是可继承的类,所以在继承它时要加上括号

改成密封类之后,方法中的else条件就不需要了。
这是因为当在when语句中传入一个密封类变量作为条件时,Kotlin编译器会自动检查该密封类有哪些子类,并强制要求你讲每一个子类所对应的的条件全部处理。

另外,密封类及其所有子类只能定义在同一文件的顶层位置,不能把嵌套在其他类中,这是被密封类底层的实现机制所限制。

推荐阅读更多精彩内容