kotlin语法糖
kotlin
-
with
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
with方法传一个参数和一个lambda 拥有第一个参数的上下文环境 返回最后一行
with的方式和apply还有let不一样 是方法 不是扩展 感觉是apply和let的组合体
-
apply
fun <T> T.apply(f: T.() -> Unit): T { f(); return this }
调用某对象的apply方法 在函数范围内 可以调用任意这个对象的方法 并将这个对象返回
-
run
fun <T, R> T.run(f: T.() -> R): R = f()
和apply很像 不过返回的是最后一行 而不是当前对象 和let区别 闭包没有参数 可以使用this
-
let
fun <T, R> T.let(f: (T) -> R): R = f(this)
调用某对象的let方法 会将该对象传入函数体重 it调用 返回值是函数的最后一行
-
inline
将函数体直接拷贝到调用处 减少函数调用 一般内联函数都很短
内联的函数在编译的时候会被进行代码替换 因此没有函数属性 所以内联函数只允许传递给内联函数
内联函数可以执行return 而非内联只能进行局部返回
-
noline
声明不会内联
-
crossline
解决匿名函数不允许return 内联函数允许return 互相冲突导致 所以加上crossline关键字表示一定不会使用return关键字
-
data class
数据类 会自动生成equals toString等方法
-
sealed class
密封类 when方法必须实现所有的case
-
object class
单例类
-
compain object{}
伴生对象
-
operator fun plus(obj:Obj):Obj{}
重载函数 重载Obj的plus方法
-
高阶函数
高阶函数加上inline是个好习惯
fun operateNums(num1: Int, num2: Int, operate: (Int, Int) -> Int): Int { return operate(num1, num2) } fun StringBuilder.build(block: StringBuilder.() -> Unit): StringBuilder { block() return this }
-
泛型
-
泛型类
class MyClass<T> { fun method(params: T): T { return params } } val myclass = MyClass<Int>()
-
泛型方法
class MyClass { fun <T> method(params: T): T { return params } } val result = MyClass().method(123)
-
-
by 委托
可以将方法实现交给by后面的对象 这样我们可以将大部分方法交给委托对象实现 少部分需要我们自定义的或者需要修改的对象自己实现
class MySet<T>(helpSet: HashSet<T>) : Set<T> by helpSet {}
-
infix
infix 不能定义成顶层函数 必须是某个类的成员函数 必须接收且只能接收一个参数
例如 in to 等infix fun <T> Collection<T>.has(element: T): Boolean = contains(element)
-
泛型实化(reified)
-
泛型擦除
在jvm中 所有的泛型都可以被称为假泛型 因为在编译的过程中 所有的泛型都会被擦除成object对象 在运行时再反射
但是kotlin中提供了内联函数的功能 在调用时 会将方法体直接拷贝到调用处 这样也就不存在擦除的问题了 直接泛型实化了 使用关键字reified
在刚开始看kotlin的时候 发现跳转Activity都需要T::class.java 感觉太麻烦了 根本不是一个高级语法糖语言该有的状态
inline fun <reified T> startActivity(context: Context) { val intent = Intent(context, T::class.java) context.startActivity(intent) } startActivity<SettingsActivity>(this)
-
-
泛型的协变和逆变
-
协变
我们在使用的java的时候 经常遇到一个问题
Student类继承Person类
List<Student>
传递给List<Person>
会报错 因为存在安全隐患 Student是Person的子类但是List<Student> 不是List<Person>的子类
而协变的定义就是 当A是B的子类时
MyClass<A>
也是MyClass<B>
的子类 就称为泛型的协变(关键字 out)class SimpleData<out T>(val data: T?) {}
意味着我们只能对data进行读取操作 而不能改变data对象 因此也就不能用set方法进行赋值了
-
逆变
从定义上看 逆变的定义和协变完全相反 当A是B的子类时
MyClass<B>
是MyClass<A>
的子类 就称为泛型的逆变(关键字 in)
-
-
suspend
将一个函数声明为挂起函数 挂起函数之间都是可以互相调用的
-
coroutineScope
继承外部协程作用域并创建一个子协程作用域 在其作用域内的所有代码和子协程全部执行完之前 会一直阻塞当前协程 coroutineScope只能在协程作用于中或者挂起函数中使用