重要的网址
插件官网地址 (studio 有时更新不下来自己下载手动安装)
https://plugins.jetbrains.com/plugin/6954-kotlin
接口
使用关键字 interface 来定义接口(注意可选方法体的实现)
interface MyInterface {
fun bar()
fun foo() {
// 可选的方法体
}
}
接口实现
class Child : MyInterface {
override fun bar() {
// 方法体
}
//foo() 根据情况选择实现
}
扩展
概念:
能够扩展一个类的新功能而无需继承该类或使用像装饰者这样的任何类型的设计模式。 这通过叫做扩展的特殊声明完成,简单说就是这个对象的功能不能满足我,我用对象.xxxx(){}给你新添加一个属性来满足我,然后整个项目都能用这个属性
class C {
fun foo() { println("member") }
}
fun C.foo() { println("extension")
}
调用 C().foo(1) 将输出 "extension"。
实例(MutableList是系统级别):
fun MutableList<Int>.swap(index1: Int, index2: Int) {//swap(x,x)是不满足当前应用的一个自定义扩充
val tmp = this[index1] // “this”对应该列表
this[index1] = this[index2]
this[index2] = tmp
}
然后再项目里的任何用到的类里都能直接调用,而不是之前java各种单利,各种xxUtils.swap(x,x),都不需要
val l = mutableListOf(1, 2, 3)
l.swap(0, 2) // “swap()”内部的“this”得到“l”的值
扩展的作用域
package vodjk.com.utils
import android.app.Activity
fun Activity.toask(des: String) {
}
fun MutableList<Int>.swap(index1: Int, index2: Int) {
}
依此类推各种Activity.swap(xxx),各种Toask.swap(xxx),各种扩充,是不是很方便
密封类
特别类型java里的工厂模式
package com.xingen.kotlin
fun main(str: Array<String>) {
test( BaseClass.Test1() )
test( BaseClass.Test2() )
test( BaseClass.Test3 )
}
/**
* 使用when表达式
*/
fun test(instance: BaseClass)=when(instance){
is BaseClass.Test1-> instance.test()
is BaseClass.Test2-> instance.test()
is BaseClass.Test3->instance.test()
}
/**
*
* sealed修饰符修饰密封类。
*
* 密封类内部含有多个子类。
*/
sealed class BaseClass {
class Test1 : BaseClass() {
override fun test() {
println("Test1实例")
}
}
class Test2 : BaseClass() {
override fun test() {
println("Test2实例")
}
}
object Test3 : BaseClass() {
override fun test() {
println("Test3实例")
}
}
open fun test() {
println("BaseClass实例")
}
}
空安全
Kotlin 的类型系统旨在消除来自代码空引用的危险,也称为《十亿美元的错误》哈哈
允许为空
如果要允许为空,我们可以声明一个变量为可空字符串,写作 String?:
var b: String? = "abc"
b = null // ok
val l = a.length(对于这句当b=null时不会报NPE,但是这样写不是安全的)
解决方案1
if (b != null && b.length > 0) {
print("String of length ${b.length}")
} else {
print("Empty string")
}
解决方案2 kotlin的安全调用
b?.length(是安全调用操作符,写作 ?.)
如果 b 非空,就返回 b.length,否则返回 null,这个表达式的类型是 Int?。
bob?.department?.head?.name
假如一个对象为空,能不能忽略不计或者跳过呢 Elvis 操作符 就来了
java模式的写法是
val l: Int = if (b != null) b.length else -1
Elvis 操作符表达,写作 ?:
val l = b?.length ?: -1
委托
类委托
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}
class Derived(b: Base) : Base by b
fun main(args: Array<String>) {
val b = BaseImpl(10)
Derived(b).print() // 输出 10
}
Derived 的超类型列表中的 by-子句表示 b 将会在 Derived 中内部存储。 并且编译器将生成转发给 b 的所有 Base 的方法。
请注意,覆盖会以你所期望的方式工作:编译器会使用你的 override 实现取代委托对象中的实现。如果我们为 Derived 添加 override fun print() { print("abc") },该程序会输出“abc”而不是“10”。
属性委托
延迟属性(lazy properties): 其值只在首次访问时计算,
可观察属性(observable properties): 监听器会收到有关此属性变更的通知
//初始化
var index: Int by Delegates.observable(1) {
pro, oldValue, newValue ->
if (newValue == 20) {
toast("关闭")
Log.e("Test", oldValue.toString() + "关闭" + newValue)
} else {
Log.e("Test", oldValue.toString() + "开启" + newValue)
}
}
//赋值
for (i in 0..40) {index = i}
把多个属性储存在一个映射(map)中,而不是每个存在单独的字段中。
http://www.runoob.com/kotlin/kotlin-delegated.html
Lambda 表达式语法
lambda 表达式总是被大括号括着, 完整语法形式的参数声明放在括号内,并有可选的类型标注, 函数体跟在一个 -> 符号之后。如果推断出的该 lambda 的返回类型不是 Unit,那么该 lambda 主体中的最后一个(或可能是单个)表达式会视为返回值。
val sum: (Int, Int) -> Int = { x, y -> x + y }
lambda 表达式语法缺少的一个东西是指定函数的返回类型的能力,所以匿名函数就出来了
匿名函数看起来非常像一个常规函数声明,除了其名称省略了。其函数体可以是表达式(如上所示)或代码块:
fun(x: Int, y: Int): Int {
return x + y
}
this限定词
为了表示当前的 接收者 我们使用 this 表达式
1:在类的成员中,this 指的是该类的当前对象
2:在扩展函数或者带接收者的函数字面值中, this 表示在点左侧传递的 接收者 参数。
3:如果 this 没有限定符,它指的是最内层的包含它的作用域。要引用其他作用域中的 this,请使用 标签限定符:
class A { // 隐式标签 @A
inner class B { // 隐式标签 @B
fun Int.foo() { // 隐式标签 @foo
val a = this@A // A 的 this
val b = this@B // B 的 this
val c = this // foo() 的接收者,一个 Int
val c1 = this@foo // foo() 的接收者,一个 Int
val funLit = lambda@ fun String.() {
val d = this // funLit 的接收者
}
val funLit2 = { s: String ->
// foo() 的接收者,因为它包含的 lambda 表达式
// 没有任何接收者
val d1 = this
}
}
}
}
Kotlin 中创建类似 Java 的静态方法
java static 的写法
public class Utils {
public static boolean isEmpty(String string){
return string != null && string.length() == 0;
}
public static boolean isWeakEmpty(String string){
return isEmpty(string) && string.trim().length() == 0;
}
}
用法:
boolean result = Utils.isEmpty(name);
kotlin 的写法
//使用object关键字创建作用类
object Utilss {
fun isEmpty(string: String?): Boolean {
return string != null && string.length == 0
}
fun isWeakEmpty(string: String): Boolean {
return isEmpty(string) && string.trim { it <= ' ' }.length == 0
}
}
//调用方式
println(Utils.isEmpty(username))