Kotlin基础 密封类,扩展函数,运算符重载
延迟初始化
由于Kotlin中严格判空机制. 对于一些全局变量声明为 ? 可空类型, 先赋值null. 然后再合适的时机再进行创建赋值, 这个时候又需要判断非空. 由于这些零碎的步骤, lateinit关键字就为此而生.
延迟初始化lateinit , 它可以让编译器再晚些时候进行赋值, 而不需要在声明的时候就必需赋值为null
private lateinit var adapter: RecyclerAdapter
因为你明确使用了延迟加载, 在后续调用你必需能保证已经在所有调用前完成了赋值. 否则会出现UninitializedPropertyAccessException异常
为了避免重复的赋值, Kotlin提供了判断是否初始化的判断. ::Filed.isInitialized
密封类
当使用when处理分支情况时, 如果传入的是一个状态接口, 通常要处理成功, 失败, 还有一个其他情况. 而其他情况其实根本不会存在. 这个时候可以使用密封类.
Kotlin编译器会自动检查密封类有哪些子类, 并强制要求你的每一个子类所对应的条件全部处理.
密封类的关键字sealed class. 修饰类名
场景: RecyclerView#onBindViewHolder() 中处理多个类型的ViewHolder时, 使用密封类可以去除无必要的else语句, 让代码更规范.
扩展函数
扩展函数表示即使在不修改某个类的源码的情况下, 仍然可以打开这个类,向这个类添加新的函数.
在Java中, 项目中有许多的自建的Utils. 比如需要一个判断一个字符串是否是手机号时. 通常我们要创建一个StringUtils类然后添加判断方法. 其实这个判断手机号的方法应该属于String类中. 但是由于String类是Final类型, 不能复写继承. 而扩展函数却解决了这个问题.
fun String.isPhone(): boolean{
// ...
}
代码表示向String类中添加一个isPhone() 的函数. 后续使用时 字符串.isPhone() 即可
"13888887777".isPhone()
运算符重载
Java中有许多的内置运算符关键字 +,-,/, % 等, 而Kotlin允许将所有的运算符甚至其他的关键字进行重载, 从而扩展这些运算符合关键字的用法.
比方每个图书对象都有书名和价格的属性. 那么就可以使用运算法重载, 让两个图书对象+, 得出书的总价.
运算符重载使用的是operator关键字, 只要在指定的函数前面加上即可. 而指定的函数如下:
语法糖表达式 | 实际调用函数 |
---|---|
a + b | a.plus(b) |
a - b | a.minus(b) |
a * b | a.times(b) |
a / b | a.div(b) |
a % b | a.rem(b) |
a– | a.dec() |
a++ | a.inc() |
+a | a.unaryPlus() |
-a | a.unaryMinus() |
!a | a.not() |
a == b | a.equals(b) |
a > b (<, >=, <=) | a.compareTo(b) |
a..b | a.rangeTo(b) |
a[b] | a.get(b) |
a[b] = c | a.set(b,c) |
a in b | b.contains(a) |
class Book(val name: String, val price: Float){
// 重载+运算
operator fun plus(book: Book): Float{
return price + book.price;
}
}
fun main(args: Array<String>){
val book1 = Book("西游记", 100.0f)
val book2 = Book("水浒传", 90.0f)
println(book1 + book2) // println: 190.0
}
Kotlin中**String#contains()**就进行了重载,
if("Hi, Jack".contains("Jack")){}
// 使用语法糖
if("Jack" in "Hi, Jack"){}