委托
委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。
Kotlin 直接支持委托模式,更加优雅,简洁。Kotlin 通过关键字 by 实现委托。
- 类委托
- 委托属性
class App : Application() {
val database: SQLiteOpenHelper by lazy {
MyDatabaseHelper(applicationContext)
}
override fun onCreate() {
super.onCreate()
val db = database.writableDatabase
} }
Kotlin 的标准库中已经内置了很多工厂方法来实现属性的委托。
延迟属性 Lazy
第一次使用时候,执行表达式
Elvis 操作符 ?:
a?.b ?: c
?.的优先级高于?:
有时要修改某类,但不改变原类并且不显式声明子类.
对于这种情况,Java使用匿名内部类,
而Kotlin使用对象表达式(object expressions)
对象声明(object declarations)
Object 声明用来定义单例
伴生对象(companion object)
Companion Objects中定义的成员类似于Java中的静态成员
Kotlin中没有static关键字
特殊函数:
with
with是一个非常有用的函数,它包含在Kotlin的标准库中。它接收一个对象和一个扩展函数作为它的参数,然后使这个对象扩展这个函数。这表示所有我们在括号中编写的代码都是作为对象(第一个参数)的一个扩展函数,我们可以就像作为this一样使用所有它的public方法和属性。当我们针对同一个对象做很多操作的时候这个非常有利于简化代码。
内联函数与普通的函数有点不同。一个内联函数会在编译的时候被替换掉,而不是真正的方法调用。这在一些情况下可以减少内存分配和运行时开销。
inline fun <T> with(t: T, body: T.() -> Unit) { t.body() }
内联函数
操作符重载
重载操作符的函数要用operator修饰符标记
data class Point(val x: Int, val y: Int)
operator fun Point.unaryPlus() = 20
operator fun Point.get(a:Int) = y
fun main(args: Array<String>) {
val point = Point(-5, 2)
println(+point)
println(point[100]);
}
输出为:
20
2
集合和函数操作符
any count flatMap map merge zip
Kotlin的扩展是静态解析的,不具备面向对象的多态的特性
Kotlin可以直接调用C的方法
官方团队给我们提供的库
map的key为id
在Kotlin中一切都是表达式,也就是说一切都返回一个值
泛型
class TypedClass<T>(parameter: T) {
val value: T = parameter
}
上面可传参数null,下面不可以
class TypedClass<T : Context>(parameter: T) {
val value: T = parameter
}
泛型函数
fun <T> typedFunction(item: T): List<T> {
...
}
变体
out 来针对协变
in 来针对逆变
let函数在处理可null对象的时候是非常有用的
if (forecast != null) dataMapper.convertDayToDomain(forecast) el
se null
forecast?.let { dataMapper.convertDayToDomain(it) }
apply
可以避免创建builder的 方式来使用,因为对象调用的函数可以根据自己的需要来初始化自己,然
后 apply 函数会返回它同一个对象
val textView = TextView(context).apply {
text = "Hello"
hint = "Hint"
textColor = android.R.color.white
}
SAM conversions
When an object implements a SAM interface (one with a Single Abstract Method), you can pass a lambda instead. Read more about SAM-conversions.
lazy{ ... } 只能用在val类型, lateinit 只能用在var类型
可以参考lazy函数的实现以及Lazy接口的源码