Android kotlin 杂项

作者: NiceDream | 来源:发表于2017-06-07 09:33 被阅读34次

    1 字符串可以包含模板表达式 , 模板表达式以美元符( $ )开头。

    val i = 10
    val s = "i = $i" // 求值结果为 "i = 10"
    

    2 引用相等

    引用相等由 ===(以及其否定形式 !== )操作判断。a === b 当且仅当 a 和 b 指向同一个对象时求值为 true。

    3 结构相等

    结构相等由 ==(以及其否定形式 != )操作判断;
    按照惯例,像 a == b 这样的表达式会翻译成

    a?.equals(b) ?: (b === null)
    

    4 幕后字段,field

    Kotlin 中类不能有字段。当使自定义定义访问器时,有时有个幕后字段(backing field)有时是必要的。为此 Kotlin 提供一个自动幕后字段,它可通过使用 field 标识符访问;

    var counter = 0 // 此初始器值直接写⼊到幕后字段
    set(value) {
        if (value >= 0)
            field = value
    }
    

    5 幕后属性

    private var _table: Map<String, Int>? = null
    public val table: Map<String, Int>
        get() {
            if (_table == null) {
                _table = HashMap() // 类型参数已推断出
            }
            return _table ?: throw AssertionError("Set to null by another thread")
        }
    

    6 惰性初始化属性,lateinit
    如果在定义变量时(例如定义成员变量),又想该变量不为空,又不想子定义时就初始化

    该修饰符只能在类体中(不是在主构造函数中)声明的 var 属性,并且仅当该属性没有定义 getter 或 setter 时。

    该属性必须是非空类型,并且不能是原生类型。

    public class MyTest {
        lateinit var subject: TestSubject
        @SetUp fun setup() {
            subject = TestSubject()
        }
        @Test fun test() {
            subject.method() // 直接解引⽤
        }
    }
    

    7 扩展是静态解析

    扩展不能真正的修改他们所扩展的类。通过定义一个扩展,你并没有在这个类中插入新成员, 仅仅是可以通过该类型的变量点表达式去调用这个新函数;

    如果定义有成员函数和扩展函数,这两个函数有相同的接收者类型、相同的名字并且都适给定的参数,这种情况总是取成员函数。

    结果是C

    open class C
    class D: C()
        fun C.foo() = "c"
        fun D.foo() = "d"
        fun printFoo(c: C) {
        println(c.foo())
    }
    printFoo(D())
    

    可空接收者扩展

    可以为可空的接收者类型定义扩展。

    fun Any?.toString(): String {
        if (this == null) return "null"
        // 空检测之后,“this”会⾃动转换为⾮空类型,所以下⾯的 toString()
        // 解析为 Any 类的成员函数
        return toString()
    }
    

    8 扩展属性的行为只能通过明确给定的取值方法与设值方法来定义。

    val <T> List<T>.lastIndex: Int
        get() = size - 1
    

    9 扩展声明为成员

    class D {
        fun bar() { …… }
    }
    class C {
        fun baz() { …… }
        fun D.foo() {
            bar() // 调D.bar,其中的对象成员可以无需通过限定符访问
            baz() // 调C.baz
        }
    }
    

    扩展声明所在的类的实例称为分发接收者,

    扩展方法调用所在的接收者类型的实例称为扩展接收者 。

    对于分发接收者和扩展接收者的成员名字冲突的情况,扩展接收者优先。

    限定的 this语法,可以区分函数

    class C {
    fun D.foo() {
        toString() // 调 D.toString()
        this@C.toString() // 调C.toString()
    }
    

    10 类型的检查与转换

    is 和 !is 操作符

    智能转换

    fun demo(x: Any) {
    if (x is String) {
        print(x.length) // x 自动转换为字符串
    }
    }
    

    11 “不安全的”转换操作符---as
    如果转换是不可能的,转换操作符会抛出异常

    12 “安全的(” 可空)转换操作符--as?
    转换失败返回null

    13 解构声明

    所谓的解构声明就是将一个对象解构(destructure)为多个变量,也就是意味着一个解构声明会一次性创建多个变量.简单的来说,一个解构声明有两个动作:

    声明了多个变量

    将对象的属性值赋值给相应的变量

    可以从一个函数返回多个变量

    数据类,
    data class Person(var name: String, var age: Int) {
    }
    当我们对Person的实例使用解构声明时,可以这样做:
    
    var person: Person = Person("Jone", 20)
    var (name, age) = person
    
    println("name: $name, age: $age")// 打印:name: Jone, age: 20
    
    对于非数据类,需要自定义componentN
    data class Person(var name: String, var age: Int, var addr: String) {
            var mobile: String ?= null
    
        operator fun component4(): String {
            return this.mobile!!
        }
    }
    

    14 延迟初始化

    val p: String by lazy {
    // 计算该字符串
    }
    

    15 对一个对象实例调用多个方法( with)

    class Turtle {
    fun penDown()
    fun penUp()
    fun turn(degrees: Double)
    fun forward(pixels: Double)
    }
    val myTurtle = Turtle()
    with(myTurtle) { // 画⼀个 100 像素的正⽅形
    penDown()
    for(i in 1..4) {
    forward(100.0)
    turn(90.0)
    }
    penUp()
    }
    

    相关文章

      网友评论

        本文标题:Android kotlin 杂项

        本文链接:https://www.haomeiwen.com/subject/qtjofxtx.html