Kotlin学习第四章:延迟初始化和密封类

4.1对变量延迟初始化

kotlin语言特性包括变量不可变,变量不可为空等,都是为了尽可能保证程序的安全而设计的,但是这些特性也会再编码时给我们带来不少的麻烦。

例如,在你的类中有许多全局变量实例,但是为了保证它们能通过空指针检查语法标准,不得不做许多的非空判断操作保护才行,即使你非常确定它们不是为空的。

class KotlinforLearing(s:String){
	privatevarstr:String?=null
	funinit(s:String){
		str=s;
 }
	fungetStrLength():Int{
		return str?.length?:0 //在这里你就必须要判断str是否为空,但实际上它肯定会被初始化
 }
}

使用延迟初始化关键字lateinit,它可以告诉编译器,会在晚些时候进行初始化,这样就不用再一开始就对它初始化为null,此外利用::str.isInitialized可以判断是否被初始化。

class KotlinforLearing(s:String){
private lateinit var str:String
	fun init(s:String){
		if(!::str.isInitialized){
			str=s
		}
	}
	fungetStrLength():Int{
		return str.length?:0  //在这里就不用判断str是否为空了
	}
}

4.2使用密封类优化代码

密封类在很多时候能帮助你写出更加规范和安全的代码,它可以被继承。

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

fun getResultMsg(result:Result) = when(result){
	is Success -> result.msg//这里的result就是子类它是多态
	is Failure -> result.error
	else -> throw IllegalArgumentException()
}

实际上你会发现Result的结果只能是Success或者Failure不可能走到else,但如果不写Kotlin编译器就会认为这里缺少条件分支,代码无法编译通过。在这里我抛出了一个异常只为了满足编译器语法而已。另外,编写else条件还有一个潜在的风险。如果我们添加一个Unknown类并实现Result接口,用于表示未知的执行结果。但是我们忘了在getResultMsg()方法中添加相应的分支,编译器在这种情况下是不会提醒我们的,而是会在运行的时候进入else条件里,抛出异常导致程序崩溃。
所以简单的一句话 sealed就是为了取消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//这里的result就是子类 它是多态
	is Failure -> "Error is ${result.error.message}"
}

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

你可能感兴趣的:(Kotlin学习,kotlin,android)