推迟初始化和密封类

本节的 Kotlin 讲堂,咱们就来学习推迟初始化和密封类这两部分内容。

对变量延伸初始化

前面咱们现已学习了 Kotlin 言语的许多特嵌套性,包括变量不可变,变量不可为空,等安全等。这些特性都是为了尽或许地确保程序安全而规划的,可是有些时分这些特性也会在编码时给咱们带来不少的费事。

比如,假定你appearance的类中存在许多全局变量实例,为了确保它们能够满意 Kotlin 的空指针检查语法标准,你不得不做许多的非空判别保护才行,即便你十分确认它们不会为空。

下面咱们经过一个具体的比如来看一下吧嵌套结构,就运用刚刚的 UIBestPracti嵌套查询sql句子ce 项目来作为比如。假定你仔细观察 MainActivity 中的代码,会发现这儿适配嵌套结构器的写法略微有点特别:

class MainActivit变量值y : AppCompatActivity(), View.OnCli变量ckListener {
private var adapte安全教育渠道r: MsgAdapter? = null
overriappearancede fun onCreate(savedInstanceState: Bundle?) {
...
adapter = MsgAdapter(msgList)
...
}
override fun onClick(v: View?) {
...
adapter?.notifyIt接口crc过错计数emInserted(m安全教育渠道登录进口sgList.size - 1)
...
}
}

这儿咱们将安全教育渠道登录进口 adapter接口安全教育渠道登录置为了全局变量,但application是它的初始化作业是在 onCreate() 办法中进行的,变量是什么意思因此不得不先将 adapter 赋值为 null,一起把它的类型声明成 MsgAdapter?。

尽管咱们会在 onCreate() 办法中对 adapter 进行初始化,一起能确保 onCli安全教育渠道登录进口ck() 办法必定在 onCreate嵌套是什么意思() 办法之后才会调用,可是咱们在 onClick() 办法中调用 adaappreciatepter 的任何办法时依然要进行判空处理安全期计算器才行,不然接口crc过错计数编译必定无法经过。

而当你的代码中有了越来越多的全局变量实例时,这个问题就会变得越来越明显,到时分你或嵌套查询许有必要编变量与函数写很多额外的判空处理代码,仅仅为了满意 Kotlin 编译器的要求。

走运的是,这个问题其实是有处理办法的,而且十分接口是什么简略,那便是对全局变量进行推迟初始化。

推迟初始化运用的是 lateinit 要害字,它能够奉告 Kotlin 编译器,我会在晚些时分对这个变量进行初始化,这样嵌套if函数就不用在一开始的时分将它赋值为 null 了。

接下来咱们就运用推迟初始化的办法对上述代码进行优化,如下所示:

class MainActivity : AppCompatActivity(), View.OnClickListener {
private late变量的指针其意义是指该变量的init var adapter: MsgAdapter
override fun onCreate(savedInstanceState: Bundle?) {
...
adapter = M变量的界说sgAdapter(msgList)
...
}嵌套查询
override fun onClicapproachk(v:嵌套 View?) {
.appear..
adapter.no接口和抽象类的差异tifyItemInserted(msgList.size - 1approach)
...
}
}

能够看到,我嵌套函数们在 adapter 变量的前面加上了 lateinit 要害字,这样就不用在一开始的时分将它赋值为appearance null,一起类型声明也就能够改成 MsgAdapter了。由于 MsgAdapter 是不可为空的类型,所以咱们在 onClick() 办法中也就不再需求进行判空处理,直接调用 adapte接口是什么r 的任何办法就能够了。

当然,运用 lateinit 要害字也不是嵌套是什么意思没有任何危险,假定咱们在 adapter 变量还没有初始化的状况下就直接运用它,那么程序就一定会溃散,而且抛出一个 UninitializedPropertyapp是什么意思AccessException 失常。

所以变量类型有哪些,当你对一个全局变嵌套循环量运用了 lateinit 要害字安全工程时,请一定要确保它在被任何当地调用之前现已结束了初始化作业,不然 Kotlin 将无法确保程序的安全性。

其他,咱们还能够经过代码来判别一个全局变量是否现变量之间的联系已结束了初始化,这样在某些时分能够有效地避免重复对某一个变量进行初始化操作,示例代码如下:

class MainActappreciateivity : AppCompatActivity(), View.OnClickListener {
private lateinit var adapter: MsgAdapter
override fun onCreate(savedInstanceState: Bundle?) {
...
if (!::adaptapproacher.isInitialized) {
ad嵌套的拼音apter = MsgAdapter(msgList)
}
...
}
}

具体语法便是这样,::adapter.isInitialized 可用于判别 adapter 变量是否现已初始化。尽管语法看上去有点乖僻,但这是固定的写法。然后咱们再对效app下载果进行取反,假定还没有初始化,那么就立即对 adapter 变量进行初始化,不然什么都不用接口类型做。

以上便是关于推迟初始化的全部重要内容,剩余的便是在合理的当地运用它了,信任这对于你来说并不是什么难题。

运用密封安全教育渠道登录进口类优化代码

由于密封类一般能够结合 Recy接口clerView 适配器中的 Vie安全工程wHolder 一起运用,因此咱们就正好借这个机会在本节学习一下它的用法。当然,密封类的运用场景远不止嵌套查询于此,它能够在许多时分帮助你写出愈加标准和安全的代码,所以十分值得一学。

首要来了解一下密封类具体的作用,这儿咱们来看一个简略的比如。新建一个 Kotlin 文件,文件名就叫 Result.kt 好了,然后在这个文件中编写如下代码:

interface Result
class Success(val msg: String) : Result
class Failure(val error: Exception) : Resu嵌套路由lt

这儿界说了一个 Result 接口,用于标明某个操作的实施作用,接口中不用编写任何内容。然后界说了两个类去结束 Result 接口:一个 Success 类用于标明成功时的作用,一个 Failure 类用于标明失利时的作用,这样就把预备作业做好了。

接下来再界说一个 getResultMsg() 办法,用于获取毕竟实施作用的信息,代码如下所示:

fun getResultMAPPsg(result: Result) = whe嵌套调用n (result) {
is Success嵌套if函数 -> result.msg
is F接口测验ailure -> result.error.message
else -> throw IllegalArgumentException()
}

getResultMsg() 办法中接收一个 Result 参数。咱们经过 when 句子来判别:假定 Result 归于 Success,那么就回来成功的音讯;假定 Result 归于 Failure,那么就回来过错信息。

到目前为止,代码都是没有问题的,但比较让人厌烦的是,接下来咱们不得不再编写一个 else 条件,不然 Kotlin 编译器会以为这儿缺少条件分支,代码将无法编译经过。但实际上 Result 的实施作用只或许app下载是 Success 或许 Failure,这个 else 条件是永久走不到的,所以咱们在这儿直接抛出了一个失常,仅仅为了满意Kotlin编译器的语法检查算了嵌套if函数

其他,编写 else 条件还有一个潜在的危险。假定咱们现在新增了一个 Unknown 类并结束 Result 接口,用于标明不知道的实施作用,可是忘记在 getResultMsg() 办法中增加相应的条件分支,编译器在这种状况下是不会提示咱们的嵌套调用,而是会在运行的时分进入 else 条件里边,从而抛出失常并导致程序溃散。

不过好音讯是,Kotlin 的密封类能够很好地处理这个问题,下面咱们就嵌套调用来学习一下。

密封类的要害字是 sealed class,它的用法相同十分简略,咱们能够轻松地将 Result 接口改造成密封类的写法:

sealed class Result
cla变量值ss Success(val msg: Strin安全教育渠道g) : Result()
class Failure(val error: Exception) : Result()
fun getResultMsg(result: Result) = when (r变量值esult) {
is Success -> result.msg
is Failure -> result.error.messaappointmentge
}

能够看到,代码并没有什么太大的变化,仅仅将 interface 要害安全教育渠道登录字改成了 sealed class。其他,由于密封类是一个可承继的类,因此在承继它的时分需求在后面加上一对括号,这一点咱们在第 2 章就学习过了。

那么改成变量的指针其意义是指该变量的密封类之后有什么优点呢?你会发现现在 getResapp下载ultMsg() 方接口法中的 else 条件现已不再需求了。

为什么这儿去掉了 else 条件依然能编译经过呢?这是由于当在 when 句子中传入一个密封类变量作为条件时,Kotlin 编译器会主动检查该密封类有哪些子类,并强制要求你将每一个子类所对应的条件全部处理。这样就能够确保,即便没有编写 else 条件,也不或许会呈现漏写条件分支的状况。而假定咱们现在新增一个 Unknappearanceown 类,并也让它承继自 Result,approach此时 getResultMsg() 办法就一定会报错,有必要增加一个 Unknown 的条件分支才能让代码编译经过。

这便是密封类首要的作用和运用办法了。其他再多接口crc过错计数说一句,密封类及其全部子类只能界说在同一个文件的顶层方位,不能嵌套在其他类中,这是被密封类底层的结束接口类型机制所约束的。

了解了这么多关于密封类的知识,接下来咱们看一下它该怎样结合 MsgA安全教育dapter 中的 ViewHolder 一起运用,并趁便嵌套查询sql句子优化一下 MsgAdapter 中的代码。

观看 MsgAdapt安全工程er 现在的代码,你会发现 onBindViewHolder() 办法中就存在一个没有实际作用的 else 条件,仅仅抛出了一个失常算了app是什么意思。对于这部分代码,咱们就能够凭借密封类的特性来进行优化。首要删除 MsgAdapter 中的 LeftViewHolde r和 RightViewHolder,然后新建一个 MsgViewHolder.k变量类型有哪些t 文件,在其间参与如下代码:

sealed clasappointments Ms变量的指针其意义是指该变量的gViewHolder(view: View安全期是哪几天)app是什么意思 : RecyclerView.ViewHolder(view)
class LeftViewHolder(view: View) : MsgViewHolder(view) {
val leftMsg: TextView = view.findViewById(R.id.leftMsg)
}
class RighappstoretViewHolder(view: View) : MsgViewHolder(view) {
val right嵌套函数Ms嵌套的拼音g: TextView = view.findViewById(R.id.rightMsg)
}

这儿咱们界说了一个密封类 MsgVie安全工程wHolder,并让它承继自 RecyclerView.ViewHolder,然后让 LeftViewHolder 和 Rig嵌套循环htViewHolder 承继自 MappointmentsgViewHolder。这变量与函数样就相当于密封类 MsgViewHolder只要两个已知子嵌套函数类,app下载因此在 when 句子中只需处理这两种状况的条件分支即可。

现在修改 MsgAdapter 中的代码,如下所示:

class MsgAdapter(val msgList: List<接口文档Msg>) : RecyclerVie接口文档w.Adapter<MsgViewHolder>() {
...
override fun onBi嵌套函数ndViewHolder(holdeapplicationr:接口类型 MsgViewHolder, position嵌套的拼音: Int) 	{
val msg = m接口是什么sgList[position]
when (holder) {
is LeftViewHolder -> holder.leftMsg.text = msg.content
is接口的作用 RightViewHolder -> holder.rightMsg.text = msg.content
}
}
...
}

这儿咱们将 RecyclerView.Adapter 的泛型指定成刚刚界说的密封类 MsgViewHolder,这样 onBindViewHolder() 办法传入的参数就变成了 MsgViewHolder。然后咱们只需在 when 句子安全工程专业傍边处理 LeftViewHolder 和 RightViewHolder 这两appreciate种状况就能够了,那个厌烦的 else 终于不再需求了,这种 RecyclerView 适配app下载器的写法愈加标准也安全教育渠道愈加引荐。