Kotlin语法:延迟初始化和密封类学习讲解

延迟初始化

延迟初始化使用的是lateinit关键字,它可以告诉编译器,我会在晚些时候对这个变量进行初始化,这样就不用在一开始的时候给它赋值为null了.
不过使用lateinit关键字也有风险,如果在变量还没有初始化就去使用它,那么会抛出一个
UninitializedPropertyAccessException异常.
示例:

lateinit var adapter:Adapter
fun main(){ 
    println(adapter.toString())
}

运行结果:

另外,我们可以通过代码判断一个全局变量是否已经完成了初始化,这样在某些时候可以有效的避免对某一个变量重复的进行初始化操作,示例代码如下:

lateinit var adapter: Adapter
fun main() { 
    if (!::adapter.isInitialized) { 
        println("adapter has not been initialized")
    } else { 
        println(adapter.toString())
    }
}

运行结果:

具体语法就是::adapter.isInitialized可以用于判断adapter变量是否已经初始化.虽然语法看上去很奇怪,但这是固定的写法.

使用密封类优化代码

首先我们先来了解一下密封类的作用,这里我们先看个简单的例子,新建一个Result.kt文件,然后再这个文件里面编写如下代码:

interface Result
class Success(val msg: String) : Result()
class Failure(val error: Exception) : Result()

这里定义了一个Result接口,用于表示某个操作的执行结果,接口里面不编写任何内容.然后定义了2个类去实现Result接口:一个Success类用于表示成功时候的结果,一个Failure类表示失败时的结果,这样就把准备工作做好了.

接下来定义一个getResultMsg()的方法,用于获取最终指执行结果的信息,代码如下:

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

getResultMsg()方法里面有一个Result参数,我们通过when语句来判断:如果Result属于Success ,那么就返回成功的消息,如果Result属于Failure,那么就返回失败的消息.但令人讨厌的是,这里我们不得不写一个else 语句,实际上结果只可能是Success或者Failure,else 语句只是为了满足Kotlin语法,所以我们在这里就直接抛了一个异常.

我们可以用密封类来解决这个问题:
密封类的关键字是sealed class,它的用法同样非常简单,我们可以轻松的把Result类改为密封类:

sealed class Result
class Success(val msg: String) : Result()
class Failure(val error: Exception) : Result()

可以看见,我们只是将interface改为了sealed class.另外由于密封类是一个可以继承的类,因此我们在继承它的时候,会在后面加上一对括号.

那么改为密封类有什么好处呢?

我们会发现在getResultMsg()方法里面的else不需要了,而且也不会报错.这是为什么呢?因为当when语句中传入一个密封类变量作为条件时,Kotlin编译器会自动检查该密封类有哪些子类,并且强制要求每一个子类你都必需要去处理,这样就可以保证,即使没有else条件,也不会出现漏写条件分支的情况.

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

谢谢观看,一起进步鸭

本文地址:https://blog.csdn.net/I_r_o_n_M_a_n/article/details/110876873

(0)
上一篇 2022年3月21日
下一篇 2022年3月21日

相关推荐