android开发之&android中的swift,kotlin中的函数(八)

249 阅读8分钟
/** 
* 函数定义和使用 
* 在 kotlin 中用关键字 fun 声明函数: 
*/
fun main(args: Array<String>) {    
    val sum1 = sum(1,2,3,5,100)    
    println(sum1)    
    //一旦定义成可变参数,调用时可以给一个对应类型的数组,数组名前加一个星号(*)    
    //因为sum函数要求函数类型是Int,而a却是IntArray,而*a代表将这个数组全部展开,其实就是指代具体的内容    
    //加载变量名前的"*"是展开操作符    
    val a = intArrayOf(1,2,3,5,100)    
    println(sum(*a))
} 
fun suare(r:Double):Double{    
    return Math.PI * r * r
}
//变长参数(vararg):接受无限多的参数
fun sum(vararg x: Int):Int{    
    var total = 0    
    for (i in x){        
        total += i    
    }    
    return total
}

/** 
* 函数的作用范围 * 函数根据作用范围可分为:成员函数、本地函数、顶层函数 
*/
fun main(args: Array<String>) { }

/** 
* 成员函数:定义一个类、object或者接口内的函数成为成员函数 
* 调用一个string类型的实例,也就是一个字符串的成员函数 
*/fun test(){    
    val title = "kotlin教程"    
    val language = title.take(6)    
    println(language)       
} 

/** 
* 本地函数 * kotlin允许把小函数声明在其他函数内部,他们被称为本地函数或嵌套函数,可以多层嵌套 
*/
fun printArea(w:Int,b:Int){    
    fun area(w: Int,b: Int):Int{        
        return w * b    
    }    
    val area = area(w,b)    
    println("面积=$area")     
    fun area() = w * b    
    val area2 = area()    
    println("面积=$area2")
}
fun checkNumber(start: Int,end: Int){    
    for (number in start..end){        
        if (number % 3 == 0){            
            println("$number 被3整除")        
        }else if (number % 5 == 0){            
            println("$number 被5整除")        
        }else if (number % 3 ==0 && number % 5 == 0){            
            println("$number 既能被3整除,也能被5整除")        
        }else{            
            println(number)        
        }    
    }     
    fun isThrees(x:Int) = (x % 3 == 0)    
    fun isFives(x:Int) = (x % 5 == 0)    
    for (number in start..end){        
        if (isThrees(number)){            
            println("$number 被3整除")        
        }else if (isFives(number)){            
            println("$number 被5整除")        
        }else if (isThrees(number) && isFives(number)){            
            println("$number 既能被3整除,也能被5整除")        
        }else{            
            println(number)        
        }    
    }     
    for (number in start..end){        
        fun isThrees() = (number % 3 == 0)        
        fun isFives() = (number % 5 == 0)        
        if (isThrees()){            
            println("$number 被3整除")        
        }else if (isFives()){            
            println("$number 被5整除")        
        }else if (isThrees() && isFives()){            
            println("$number 既能被3整除,也能被5整除")        
        }else{            
            println(number)        
        }    
    }     
    for (number in start..end){        
        fun isThrees() = (number % 3 == 0)        
        fun isFives() = (number % 5 == 0)         
        when {            
            isThrees()              -> println("$number 被3整除")            
            isFives()               -> println("$number 被5整除")            
            isThrees()&&isFives()   -> println("$number 既能被3整除,也能被5整除")            
            else -> println()        
        }    
    }
} 

/** 
* 顶层函数:即这些函数不属于任何源码文件,而是直接定义在源码文件中的 
* 在定义通用性的工具栏和帮助类函数时非常有用 
*/
fun salary(k:Int){    
    require(k > 4000,{"最低工资不能少于4000!"})    //这3个函数其实有一个术语,交断言,同时也有assert这个函数,把这种功能的函数添加到一个class中毫无意义,可以专门存放在一个kotlin源文件中
}

/** 
* 命名参数和默认参数 
*/
fun main(args: Array<String>) {    
    /**     
    * 命名参数     
    */    
    fun fotmat(str:String,state:Boolean = false){        
        println(str + ":" + state)    
    }    
    fotmat(str = "hello",state = true)     
    val book = "基于Kotlin的Android"    
    println(book.regionMatches(9,"深入android",2,7,true))    
    //函数参数非常多    
    book.regionMatches(thisOffset = 9,other = "深入Andorid",length = 2,otherOffset = 7,ignoreCase = true)//可读性更高,不过就是麻烦    
    
    /**     
    * 默认参数     
    * 给函数的某些参数提供默认值     
    */     
    //默认值可以通过在type类型后使用=号进行赋值    
    fun read(b:Array<Byte>,off:Int = 0,len : Int = b.size ){     }     
    book.endsWith(suffix = "Android",ignoreCase = true)    
    book.endsWith(suffix = "Android")//可以忽略掉ignoreCase的调用,因为ignoreCase默认值是false    
    //默认参数也可以用到构造函数中,从而避免产生更多的二次构造函数    

    class User(val name:String,val isVip:Boolean,credits:Int){        
        constructor(name:String):this(name,false,0)        
        constructor(name:String,isVip:Boolean):this(name,isVip,0)    
    }    
    //可以改写成    
    class User2(val name:String,val isVip:Boolean=false,credits:Int = 0)  
}

/** 
* 函数操作符 
* 函数的操作符用了一个符号来标识,有很多内置的操作符 
*/
fun main(args: Array<String>) {    
    val m = Matrix(8,8,8,8)    
    val n = Matrix(9,9,9,9)    
    val mu = m + n    

    //与下面代码等价    
    val mu2 = m.plus(n)      
    val mm = Matrix2(8,8,8,8)    
    println(mm[0,0])    
    mm[0,0] = 5    
    println(m.a)      
    Minvalue(-300,0)    
    Minvalue(1,2,3)    
    Minvalue(5,6,7,8)     
    /**     
    * 比较操作符     
    */    
    val tom = Student("Tom Green",15)    
    val lily = Student("Lily Smith",14)    
    val jerry = Student("Jerry Patrick",16)    
    val lucy = Student("Lucy Smith",14)    
    println(tom < lily)     //false    
    println(lucy >= jerry)  //false    
    println(jerry > lily)   //true    
    println(tom <= jerry)   //true     
    //赋值操作符    
    var counter = Counter(2)    
    counter = counter + 3    
    counter += 8    
    val counter2 = QuickCounter(1)    
    counter2 *= 10
}
/** 
* 操作符重载:使用操作符定义函数的能力被称为操作符重载 
*/
class Matrix(val a:Int,val b:Int,val c:Int,val d:Int){    
    operator fun plus(m:Matrix):Matrix{        
        return Matrix(a + m.a,b + m.b,c + m.c,d+m.d)    
    }
}
/** 
* 基础操作符 
* 操作                   函数名 
* !x                    x.not() 
* -y                    y.unaryMinus() 
* +z                    z.unaryPlus() 
* a..b                  a..rangeTo(b) 
* c + d                 c.plus(d) 
* c - f                 e.minus(f) 
* g * h                 g.times(h) 
* i / j                 i.div(j) 
* m % n                 m.mod(n) 
*/ 
/** 
* In和contains 
* 关键字in在循环和集合类型的操作中常用,同样可以在自己的类中使用。in对应的名字是contains 
*/
val numbers = arrayListOf(5,6,7,8)
val a = 6 in numbersval 
b = numbers.contains(3)
val c = 7 !in numbers
val d = !numbers.contains(7) 
/** 
* Get/Set:数组取元素的中括号语法对应get和set 
*/
val element = numbers[1]
class Matrix2(var a:Int,var b:Int,var c:Int,var d:Int){    
    operator fun plus(m:Matrix2):Matrix2{        
        return Matrix2(a+m.a,b+m.b,c+m.c,d+m.d)    
    }    
    operator fun get(horizontal:Int,vertical:Int):Int{        
        val point = Pair(horizontal,vertical)        
        when (point) {            
            Pair(0,0) -> return a            
            Pair(0,1) -> return b            
            Pair(1,0) -> return c            
            Pair(1,1) -> return d            
            else -> {                
                return 0            
            }        
        }    
    }    
    operator fun set(horizontal: Int,vertical: Int,value:Int) {        
        val point = Pair(horizontal, vertical)        
        when (point) {            
            Pair(0, 0) -> this.a = value            
            Pair(0, 1) -> this.b = value            
            Pair(1, 0) -> this.c = value            
            Pair(1, 1) -> this.d = value            
            else -> {                
                return            
            }        
        }    
    }
} 
/** 
* Invoke和() 
* 圆括号也可以通过重载invoke函数作为操作符 
*/
object Minvalue{    
    operator fun invoke(a:Int,b:Int) = if (a > b) a else b    
    operator fun invoke(x:Int,y:Int,z:Int) = invoke(invoke(x,y),z)    
    operator fun invoke(h:Int,i:Int,j:Int,k:Int) = invoke(invoke(h,i), invoke(j,k))
} 
/** 
* 比较操作符 
*/
class Student(val name:String,val age:Int){    
    operator fun compareTo(other:Student):Int{        
        return when{            
            age > other.age -> 1            
            age > other.age -> -1            
            else -> 0        
        }    
    }
} 
/** 
* 赋值操作符 * 对于可变类型或变量,kotlin支持重载他们类型的赋值操作符或组合赋值操作符,如:+、*= 
*/
class Counter(val a :Int){    
    operator fun plus(b:Int) = Counter(a + b)
}
class QuickCounter(var a:Int){    
    operator fun timesAssign(b:Int){        
        a *= b    
    }
}

/** 
* 函数扩展 
*/
fun main(args: Array<String>) {    
    3.square()     
    val number2 = MyNumber(8)    
    number2.addFactor(3)    
    println(number2.k)      
    val al = Element("铝")    
    al.react(Particle())    
    al.react(Electron())    
    val neon = NobleGas("氪")    
    neon.react(Particle())    
    neon.react(Electron())      
    val train = "北京" to "伤害"    
    println(train) 
}
//在函数名前加上类型和点。这个被扩展的类型,称为接收者类型。也就是说这个接收者类型被进行了函数扩展。this代表类型实例的引用
fun Int.square() = this * this 
/** 
* 扩展函数的优先级 
* 扩展函数不能重载类型或接口中已定义的函数。如果定义了一个与既有函数一模一样的扩展函数,这个扩展其实是无效的 
*/ 
/** 
*扩展函数的作用范围 
*/
class MyNumber(var k:Int){    
    //Int的三次方扩展函数triple仅在MyNumber类之内生效,之外无法使用    
    private fun Int.triple() = this * this * this    
    fun addFactor(p:Int){        
        k += p.triple()    
    }
} 
/** 
* 扩展函数在子类中的重载 
*/
open class Particle()
class Electron: Particle() 

open class Element(val name:String){    
    open fun Particle.react(name:String):Unit{        
        println("$name 与粒子发生反应")    
    }    
    open fun Electron.react(name: String):Unit{        
        println("$name 与电子发生反应生成同位素。")    
    }    
    fun react(particle: Particle):Unit{        
        particle.react(name)    
    }
}
class NobleGas(name: String):Element(name){    
    override fun Particle.react(name: String):Unit{        
        println("$name 是稀有气体,不能与粒子发生反应")    
    }    
    override fun Electron.react(name: String):Unit{        
        println("$name 是稀有气体,不能与电子发生反应")    
    }    
    fun react(particle: Electron):Unit{        
        particle.react(name)    
    }
} 
/** 
* infix中缀函数:中缀函数是二元的,必须有2个参数,第一个是实例,第二个是参数 
*/
infix fun String.to(other:String):String{    
    return this + other
}

/** 
* 尾递归函数 
*/
fun main(args: Array<String>) { }

fun fibo(total:Int):Int = when(total){    
    0       ->  1    
    1       ->  1    
    else    ->  fibo(total - 1) + fibo(total - 2)
} 

fun fact(k:Int):Int{    
    fun factTail(m:Int,n:Int):Int{        
        if (m == 0) return n        
        else return factTail(m - 1,m * n)    
    }    
    return factTail(k,1)
}
//这个内部的factTail即是尾递归,那就可以标记为tailrec
fun fact2(k:Int):Int{    
    tailrec fun factTail(m:Int,n:Int):Int{        
        if (m == 0) return n        
        else return factTail(m - 1,m * n)    
    }    
    return factTail(k,1)
}

/** 
* 标准库函数 
*/
fun main(args: Array<String>) {    
    /**     
    * apply函数是标准库对Any类型的一个扩展,所以任何类型的实例都可以调用。apply调用的时候接受一个Lambda表达式,     
    * 可以任意调用该对象的任意方法,然后返回该对象     
    */    
    val task = Runnable { println("运行中") }    
    Thread(task).apply { setDaemon(true) }.start()    
    //另一个写法是不用apply的    
    val task2 = Runnable { println("Running") }    
    val thread = Thread(task2)    
    thread.setDaemon(true)    
    thread.start()     

    /**     
    * let默认当前这个对象最为闭包的it参数,返回值是函数里面最后一行,或者指定return     
    */    
    fun myLet():Int{        
        "myLet".let {            
            println(it)            
            return 999        
        }    
    }//打印:myLet  999     
    
    /**     
    * with:有时候一个要执行一个对象的很多个方法势必要写很多次对象名     
    * with和let组合的例子     
    */    
    fun testMyWith(){        
        with(ArrayList<String>()){            
            add("test1")            
            add("test2")            
            add("test3")            
            println("this = " + this)        
        }.let { println(it) }    
    }//结果:this = [test1,test2,test3] kotlin.Unit     

    /**     
    * run:run函数和apply函数很像,只不过run函数是使用最后一行的返回,apple返回当前自己的对象。     
    * run就是with和let的组合式扩展     
    */    
    ArrayList<String>().run {        
        add("test1")        
        add("test2")        
        add("test3")        
        add("test4")        
        println(this.joinToString())    
    }//结果:test1,test2,test3,test4     

    /**     
    * lazy:可以把非常耗费资源的操作延迟到第一次调用时在加载     
    */    
    //耗时操作    
    fun readStringFromURL():String = ""    
    val lazyString = lazy { readStringFromURL() }    
    //第一次请求结果的时候,才能访问到这个延迟加载的引用    
    val string = lazyString.value     

    /**     
    * Use:和try语句有点相似。use被用于一个可closable的实例且有一个可操作这个closable的闭包。     
    * use会安全的调用这个函数,在函数调用完成后关闭占用的资源,不管是否出现异常     
    */
    val input = Files.newInputStream(Paths.get("input.txt"))
    val byte = input.use { {input.read()} }     

    /**     
    * Repeat:重复执行一个闭包指定次数。repeat的参数接受一个Int型参数来指定带次数,     
    * 一个闭包用来包含要执行的语句     
    */    
    repeat(8,{ println("kotlin重复执行")})//结果:kotlin重复执行   执行8次     

    /**     
    * require/assert/check     
    * require会抛出一个异常,用来确保参数复合输入条件     
    * assert会抛出一个AssertionException异常,用来确保内部状态整合     
    * check会抛出一个IllegalStateException异常,用来确保内部状态整合     
    */    
    fun qreaterThanZero(x:Int){        
        require(x > 0,{"数字必须大于0"})        
        println(x)    
    }
}

/** 
* 泛型函数 
*/
fun main(args: Array<String>) {    
    val array = arrayOf(1,3,5,-8)    
    println("${array.joinToString()}中最大的值是${array.biggest()}")    //结果:1,3,5,-8中最大的值是5
}
fun <T> outputString(a:T,b:T,c:T):String{    
    return "$a,$b,$c"
} 
/** 
* 泛型函数扩展:去数字型数组中最大的一个元素 
* where语句,对泛型T的限制,使其在我们想要的边界类型之内,这里的T是Number类型,并且实现了Comparable可比较接口 
* 这个biggest就是系统提供的max函数的相似实现 
*/
fun <T> Array<T>.biggest():T    
    where T : Number,    
    T: Comparable<T>{        
        var biggest = this[0]        
        for (i in 1..lastIndex){            
            val e = this[i]            
            if (e > biggest){                
                biggest = e            
            }        
        }        
        return biggest    
    }