Kotlin 进阶之路8 程序结构

作者: 香沙小熊 | 来源:发表于2018-05-23 17:31 被阅读72次

    Kotlin 进阶之路 目录

    常量

    • val = value,值类型
    • 类似Java的final
    • 不可能重复赋值
    - 运行时常量:val x =getX()
    - 编译期常量:const val x = 2
    

    变量

    • val = variable
    - var x = "HelloWorld"//定义变量
    - x = "Hello,China"//再次赋值
    

    类型推导

    • 编译器可以推导量的类型
    - val string ="Hello" //推导出String类型
    - val int = 5 //Int 类型
    - var x = getString() + 5 //String类型 
    

    函数

    • 以特定功能组织起来的代码块
    - fun[函数名]([参数列表]):[返回值类型]{[函数体]}
    - fun[函数名]([参数列表]) = [表达式]
    

    举例:

    - fun sayHi(name:String) { println("Hi,$name") }
    - fun sayHi(name:String) = println("Hi,$name")
    

    匿名函数

    • fun([参数列表])...
    - val sayHi = fun(name:String) = println("Hi,$name")
    

    编写函数的注意事项

    • 功能单一
    • 函数名要做到顾名思议
    • 参数个数不要太多

    Lambda 表达式

    • 匿名函数
    • 写法:{[参数列表]->[函数体,最后一行是返回值]}
    - val sum = {a:Int,b:Int->a + b }
    
    Lambda的类型举例
    • ()->Unit
    无参,返回值为Unit
    
    • (Int)->Int
    传入整型,返回一个整型
    
    • (String,(String)->String)->Boolean
    - 传入字符串、Lambda表达式,返回Boolean
    
    Lambda表达式的调用
    • 用()进行调用
    • 等价于invoke()
    - val sum = {a:Int,b:Int -> a + b}
    - sum(2,3)
    - sum.invoke(2,3)
    
    Lambda表达式的简化
    • 函数参数调用时最后一个Lambda可以移出去
    • 函数参数只有一个Lambda,调用时小括号可以省略
    • Lambda只有一个参数可默认为it
    • 入参,返回值与形参一致的函数可以用函数引用的方式作为实参传入
    fun main(args: Array<String>) {
    
        println(int2Long(3))
        println(sum(2, 3))
        println(sum2(5, 6))
        println(sum.invoke(1, 3))
    
        val args: Array<Int> = arrayOf(1, 2, 3, 4, 5, 6)
        for (i in args) {
            println(i)
        }
        args.forEach(::println)
        println("--------------------------------")
        args.forEach ForEach@{
            if (it == 2) return@ForEach
            println(it)
        }
        println("The End 1.....")
        args.forEach {
            if (it == 3) return
            println(it)
        }
        println("The End 2.....")
    }
    
    val int2Long = fun(x: Int): Long {
        return x.toLong()
    }
    
    val sum = { arg1: Int, arg2: Int -> arg1 + arg2 }
    
    val sum2 = { arg1: Int, arg2: Int -> println("$arg1 + $arg2 = ${arg1 + arg2}") }
    
    3
    5
    5 + 6 = 11
    kotlin.Unit
    4
    1
    2
    3
    4
    5
    6
    1
    2
    3
    4
    5
    6
    --------------------------------
    1
    3
    4
    5
    6
    The End 1.....
    1
    2
    

    类成员

    • 属性:作者说成员变量,类范围内的变量
    • 方法:或者说成员函数,类范围内的函数

    函数和方法的区别

    • 函数强调功能本身,不考虑从属
    • 方法的称呼通常是从类的角度出发
    • 叫法不同而已,不要纠结

    定义属性

    • 构造方法参数中val/var修饰的都是属性
    • 类内部也可以定义属性

    属性访问控制

    • 属性可以定义getter/setter
    - val a:Int = 0 //不能定义set()
    - get() = field
    - var b:Float = 0f //可以定义getter/setter
    - set(value){field = value}
    

    属性初始化

    • 属性的初始化尽量在构造方法中完成
    • 无法在构造方法中初始化,尝试降级为局部变量
    • var用lateinit延迟初始化,val用lazy
    • 可空类型谨慎用null直接初始化
    class X
    //lateinit 延迟初始化
    class A {
        var b = 0
        lateinit var c: String
        lateinit var d: X
        val e: X by lazy {
            println("init X")
            X()
        }
        //可空类型谨慎用null直接初始化
        var cc: String? = null
    }
    
    fun main(args: Array<String>) {
        println("start")
        val a = A()
        println("init a")
        println(a.b)
        println(a.e)
    
        a.d = X()
        println(a.d)
    
        println(a.cc?.length)
    }
    
    start
    init a
    0
    init X
    chapter3.X@7106e68e
    chapter3.X@7eda2dbb
    null
    

    基本运算符

    • 任何类可以定义或者重载父类的基本运算符
    • 通过运算符对应的具体函数来定义
    • 对参数个数作要求,对参数和返回值类型不作要求
    • 不能像Scale一样定义任意运算符

    中缀表达式

    • 只有一个参数,且用infix修饰的函数
    - class Book{ infix fun on(place:String){...}}
    - Book() on "My Desk"
    

    分支表达式

    • if...else
    - if(a ==b ) ... else if(a == c) ... else ...
    
    • 表达式与完备性
    - val x = if(b < 0) 0 else b
    - val x = if(b < 0) 0 //错误,赋值时,分支必须完备
    
    private const val USERNAME = "kotlin"
    private const val PASSWORD = "jetbrains"
    
    private const val ADMIN_USER = "admin"
    private const val ADMIN_PASSWORD = "admin"
    
    private const val DEBUG = 1
    private const val USER = 0
    
    fun main(args: Array<String>) {
    
        //1.变量赋值
    //    var mode = USER
    //    if (args.isNotEmpty() && args[0] == "1") {
    //        mode = DEBUG
    //    }
    //2. 表达式给变量赋值
        val mode = if (args.isNotEmpty() && args[0] == "1") {
            DEBUG
        } else {
            USER
        }
    
        println("请输入用户名:")
        val username = readLine()
        println("请输入密码:")
        val password = readLine()
    
        if (mode == DEBUG && username == ADMIN_USER && password == ADMIN_PASSWORD) {
    
            println("管理员登录成功")
        } else if (username == USERNAME && password == PASSWORD) {
            println("登录成功")
        } else {
            println("登录失败")
        }
    

    When 表达式

    • 加强版switch,支持任意类型
    • 支持纯表达式条件分支(类似if)
    • 表达式与完备性
    fun main(args: Array<String>) {
        val x = 5
        when (x) {
            is Int -> println("Hello $x")
            in 1..100 -> println("$x is in 1..100")
            !in 1..100 -> println("$x is not in 1..100")
            args[0].toInt() -> println("$x == args[0]")
        }
    }
    
    Hello 5
    

    循环语句

    for循环
    • 基本写法
    - for(element in elements)...
    
    • 给任意类实现Iterator方法
    fun main(args: Array<String>) {
    
        val args: Array<Char> = arrayOf('a', 'b', 'c', 'd')
        for (arg in args) {
            println(arg)
        }
        println("-------------------------------")
        for ((index, value) in args.withIndex()) {
            println("$index -> $value")
        }
        println("-------------------------------")
        for (indexedValue in args.withIndex()) {
            println("${indexedValue.index} -> ${indexedValue.value}")
        }
        println("-------------------------------")
        val list = MyIntList()
        list.add(1)
        list.add(2)
        list.add(3)
    
        for (i in list) {
            println(i)
        }
    }
    
    class MyIterator(val iterator: Iterator<Int>) {
        operator fun next(): Int {
            return iterator.next()
        }
    
        operator fun hasNext(): Boolean {
            return iterator.hasNext()
        }
    }
    
    class MyIntList {
        private val list = ArrayList<Int>()
    
        fun add(int: Int) {
            list.add(int)
        }
    
        fun remove(int: Int) {
            list.remove(int)
        }
    
        operator fun iterator(): MyIterator {
            return MyIterator(list.iterator())
        }
    }
    
    a
    b
    c
    d
    -------------------------------
    0 -> a
    1 -> b
    2 -> c
    3 -> d
    -------------------------------
    0 -> a
    1 -> b
    2 -> c
    3 -> d
    -------------------------------
    1
    2
    3
    
    While循环

    类似于C语言

    跳过和终止循环
    • 跳过当前循环用continue
    • 终止循环用break
    • 多层循环嵌套的终止结合便签使用
    - Outter@for(...){
         Inner@while(i < 0){ if(...) break } //结束while循环
          Inner@while(i < 0){ if(...) break@Outter }//结束外层for循环
    }
    

    具名参数

    • 给函数的时参附上形参
    • 举例:
    - fun sum(arg1:Int,arg2:Int) = arg1 + arg2
    - sum(arg1 = 2, arg2 = 3)
    

    变长参数

    • 某个参数可以接收多个值
    • 可以不为最后一个参数
    • 如果传参时有歧义,需要使用具名参数
    fun main(vararg args: String) {
    //    for (arg in args) {
    //        println(arg)
    //    }
        hello(18.0,1,2,3,4,string ="Hello")
    
        val array = intArrayOf(5,4,3,2,1)
        hello(18.0,*array,string ="Hello")
    }
    
    fun hello(double: Double,vararg ints: Int, string: String) {
        ints.forEach(::println)
    }
    
    1
    2
    3
    4
    5
    4
    3
    2
    1
    

    本章知识点示例

    fun main(args: Array<String>) {
        while (true) {
            try {
    
                println("请输入算式例如:3 + 4")
                val input = readLine() ?: break
                if (input != null) {
                    val splits = input.trim().split(" ")
                    if (splits.size < 3) {
                        throw IllegalArgumentException("参数个数不对")
                    }
                    val arg1 = splits[0].toDouble()
                    val op = splits[1]
                    val arg2 = splits[2].toDouble()
                    println("$arg1 $op $arg2 = ${Operator(op).apply(arg1, arg2)}")
    
    
                }
            } catch (e: NumberFormatException) {
                println("您输入的数字格式不对")
            } catch (e: IllegalArgumentException) {
                println("请输入用空格分隔的三个参数")
            } catch (e:Exception){
                println("未知异常:${e.message}")
            }
            println("再来一发?[Y]")
            val cmd = readLine()
            if (cmd == null || cmd.toLowerCase() != "y") {
                break
            }
        }
    
    }
    
    class Operator(op: String) {
        val opFun: (left: Double, right: Double) -> Double
    
        init {
            opFun = when (op) {
                "+" -> { l, r -> l + r }
                "-" -> { l, r -> l - r }
                "*" -> { l, r -> l * r }
                "/" -> { l, r -> l / r }
                "%" -> { l, r -> l % r }
                else -> {
                    throw UnsupportedOperationException(op)
                }
            }
    
        }
    
        fun apply(left: Double, right: Double): Double {
            return opFun(left, right)
        }
    }
    
    请输入算式例如:3 + 4
    566.33.33 + 1
    您输入的数字格式不对
    再来一发?[Y]
    y
    请输入算式例如:3 + 4
    23+1
    请输入用空格分隔的三个参数
    再来一发?[Y]
    y
    请输入算式例如:3 + 4
    5 + 6 
    5.0 + 6.0 = 11.0
    再来一发?[Y]
    

    相关文章

      网友评论

      本文标题:Kotlin 进阶之路8 程序结构

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