Kotlin初阶(2)

655 阅读4分钟

Kotlin初阶(2)

第一篇入口:Kotlin初阶(2)

Kotlin初阶易错知识点

9、数字定义(可以用"_"来区别很长的数字)

    //使用下划线使数字常量更易读
    val oneMillion = 1_000_000
    val creditCardNumber = 1234_5678_9012_3456L
    val socialSecurityNumber = 999_99_9999L
    val hexBytes = 0xFF_EC_DE_5E
    val bytes = 0b11010010_01101001_10010100_10010010

10、for循环(极其方便)

fun forCircle() {
        for (i in 1..5 step 1) {
            print(i)
            //输出12345
        }
        for (i in 5 downTo 1 step 1) {
            print(i)
            //输出54321
        }
        for (i in 1..5 step 2) {
            print(i)
            //输出13
        }
        for (i in 1 until 5 step 1) {
            print(i)
            //输出1234,没有5 等同于[1,5)
        }
    }

11、类型替代(typealias)

typealias f = Foo//类型替代(f代表新的名词,Foo代表需要另起名字的对象名,比如,Foo全名为:尼古拉斯.凯奇.赵四,那么f可以叫做赵四,哪里需要这么高大上的名称)

12、is和!is

    fun getStringLength(obj: Any): Int? {
        if (obj !is String) {
            return null
        }
        //此时obj已经自动转化为string类型
        return obj.length
    }

13、lambda表达式使用之一

//limbda表达式
val sumLambda: (Int, Int) -> Int = { x, y -> x + y }//xy是入参,x+y是返回值

14、长度可变的入参(关键字:vararg)

    //可变长度入参
    fun sum5(vararg v: Int): Int {
        var sum = 0
        for (vt in v) {
            sum += vt
        }
        return sum
    }

15、类相关(主构造函数,次构造函数,init方法,默认参数,变量的get和set方法,super父类方法,重写父类方法,共有函数,私有函数)

class Runoob constructor(name1: String = "jack", psd1: String = "123456") {//默认参数
//主构造器中不能包含任何代码,初始化代码可以放在初始化代码段中,初始化代码段使用 init 关键字作为前缀
init {
    println("name : $name1, psd : $psd1")
//    name = ""//这里连name常量都没有定义,所以不能够进行赋值
}

    constructor(name: String, psd: String, addr: String) : this(name, psd) {
        this.name = name
        this.psd = psd
    }

    //次构造函数
    constructor(name: String, psd: String, age: Int) : this(name, psd) {
    }

    var nickName = name1
        get() {
            return nickName
        }

    var name: String
        get() {
            return name.toUpperCase()
        }
        set(value) {
            name = value
        }
    var psd: String = ""
        private set
        get() {
            return psd + "@"
        }
}

16、interface的方法体是否实现是可选的。属性也是抽象的,需要实现类重新赋值。

interface BaseView {
	var mNickName: String//抽象的属性
    fun walk() {//方法体是否实现是可选的
        println("BaseView,walk!!!")
    }

    fun yeal() {}//
}

17、密封类

//密封类
sealed class Expr//相当于枚举的扩展

data class Const(val number: Double) : Expr()//这里只有另外一个double的状态入参
data class Sum(val e1: Expr, val e2: Expr) : Expr()//这个密封类里面就有两个Expr的状态入参
object NotANumber : Expr()

fun eval(expr: Expr): Double = when (expr) {
    is Const -> expr.number
    is Sum -> eval(expr.e1) + eval(expr.e2)
    NotANumber -> Double.NaN
    //因为已经覆盖了所以的情况,就不需要else子句了
}

18、枚举

    Color.BLACK.name
    enumValues<Color>().size
    enumValues<Color>().get(0)
    enumValues<Color>().plus(Color.WHITE)
    enumValues<Color>().iterator()
    enumValueOf<Color>(Color.WHITE.toString())

19、list和Comparable

fun <T : Comparable<T>> sort(list: List<T>) {
}
    sort(listOf(1, 2, 3)) // OK。Int 是 Comparable<Int> 的子类型
    // 错误:HashMap<Int, String> 不是 Comparable<HashMap<Int, String>> 的子类型
//    sort(listOf(HashMap<Int, String>()))

20、object对象

    val site = object {
        var name = "jack"
        var url = "www.tansu.com"
    }

21、委托类,委托对象(通过关键字 by 建立)

interface MyBase {
    fun bark()
//    fun bak()
}

class BaseImpl(val x: Int) : MyBase {
    fun bak() {}
    override fun bark() {
        println("x:$x")
    }
}

// 通过关键字 by 建立 委托类
class Deried(b: MyBase) : MyBase by b

fun test3() {
    var baseImpl = BaseImpl(10)
    Deried(baseImpl).bark()
    baseImpl.bak()
//    Deried(baseImpl).bak()//无法访问到非interface定义的方法
}

// 定义包含属性委托的类
class Example {
    var p: String by Delegate()
    //说明:如果p是var的话,那么委托类需要有getValue和setValue两个方法(因为此时是可变的变量,需要由set方法)
    //说明:如果p是val的话,那么委托类只需要有getValue方法即可,另外一个可以不要求(此时为不可变常量,不需要set值进去)
}

// 委托的类
class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, 这里委托了 ${property.name} 属性"//这里name为p
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$thisRef${property.name} 属性赋值为 $value")//value为设置进来的值
    }
}

fun test4() {
    val e = Example()
    println(e.p)     // 访问该属性,调用 getValue() 函数

    e.p = "Runoob"   // 调用 setValue() 函数
    println(e.p)
//    Example@433c675d, 这里委托了 p 属性
//    Example@433c675d 的 p 属性赋值为 Runoob
//    Example@433c675d, 这里委托了 p 属性
}

21、监听类值的变化

class User {
    var name: String by Delegates.observable("初始值") { prop, old, new ->
        println("旧值:$old -> 新值:$new. prop:$prop")
    }
}
    val user = User()
    user.name = "第一次赋值"
    user.name = "第二次赋值"
//    旧值:初始值 -> 新值:第一次赋值
//    旧值:第一次赋值 -> 新值:第二次赋值

22、map

//把属性储存在映射中
class MyWebSite(val map: Map<String, Any?>) {
    val name: String by map
    val url: String  by map
}
使用
    var myWebSite = MyWebSite(mapOf("name" to "jack", "url" to "www.baidu.com"))
    myWebSite.name
    myWebSite.url
    //结果读取出来

23、其它

class Foo {
    var notNullBar: String by Delegates.notNull<String>()
}
使用
    var foo = Foo()
    foo.notNullBar = "bar"
    println(foo.notNullBar)

第一篇入口:Kotlin初阶(2)