变量的延迟初始化

class AbcActivity : ComponentActivity() {


    private var person: Person? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_abc)

        person = Person(30);
    }


    fun doWork() {

        val a = person?.age
    }
}

将person设置成全局变量,Person的初始化在oncreate()中,所以person赋值为null,需要把类型声明Person?。
在doWork()中,person调用任何方法都要进行判空处理。
当全局变量越来越多,可能需要编写大量的判空处理代码。解决这个问题需要使用延迟初始化,延迟初始化使用lateinit关键字。

class AbcActivity : ComponentActivity() {


    private lateinit var person: Person

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_abc)

        person = Person(30);
    }


    fun doWork() {

        val a = person.age
    }
}

判断全局变量是否完成了初始化。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_abc)

        if (!::person.isInitialized) {

            person = Person(30)
        }
    }

::person.isInitialized可用于判断变量是否已经初始化。

使用密封类优化代码

创建Result.kt文件

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

编写getResultMsg()函数,处理result

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

使用上面的代码,必须实现else条件,编译器会认为这里缺少条件分支。其实只有两种情况Success和Failure。
另外,如果新增class并实现Result接口,没有在getResultMsg()添加相应的条件分支,在运行时会进入else条件里面。
kotlin使用sealed class处理了这个问题,将Result接口改成密封类。

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

去掉else,没有报错

    fun  getResultMsg(result: Result) = when(result){

        is Success ->result.msg
        is Failure -> result.error.message
    }

没有报错的原因是,当在when语句中传入一个密封类变量作为条件时,Kotlin编译器会自动检查改密封类有哪些子类,并强制要求你将每一个子类所对应的条件全部处理。不会出现漏写条件分支的情况。在Result.kt中新增一个Un类。

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

getResultMsg()方法会报错,要求处理新的分支问题。

密封类及其子类只能定义在同一个文件的顶层位置,不能嵌套在其他类中。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐