Hello word
前言:上次学习安卓,学了Java开发,简单的搭了几个安卓界面。这次要学习Kotlin语言,然后开发安卓,趁着还年轻,学点新东西,坚持~
未来的你会感谢现在努力的你~

主要学习资料:
- 《第一行代码Android 第三版》
 - 菜鸟教程
 - android官网-kotlin
 - Kotlin 官方文档 中文版
 - 2018年黑马安卓开发视频教程
 
那么,开始吧~
开始-Kotlin语言-安卓开发学习
首先是搭建环境,在一通操作过后,在android studio上成功安装行了kotlin
 经典的:hello word

eclipse环境搭建结果:
参数
又是一个绕不开的话题
 kotlin中
 使用val修饰的变量,是不可变的(value)
 使用var修饰的变量,是可变的(variable 可变的)
- tips: 优先使用val来声明一个变量,而当val没有办法满足你的需求时再使用var
 
函数的格式:
kotlin:
func 函数名(参数名: 参数类型): 返回值类型{
	函数体
}
 
oc:
- (返回值类型)函数名(参数类型: 参数名) {
	函数体
}
 
只是组合方式不一样
 函数的四要素:函数名、参数、返回值类型、函数体都有
函数的简略写法:
fun sum(a: Int, b: Int): Int{
    return a+b
}
//如果函数体里面只有一条语句,而且该语句有返回值,则可以去掉{},并省略return,直接使用=:
fun sum2(a: Int, b: Int): Int = a+b
 
在kotlin中,函数和参数(变量)一样,都是一等公民
 那个,也可以将函数表达式赋值给一个变量:
	///等号右边,称为:函数表达式
    var i = {a: Int, b: Int -> a+b}
    println(i(3, 8))
 
还有另外一种写法:
	//var j:后面,表面是一种类型,j是一个函数类型,两个入参,一个出参
	//=后面,是一个函数表达式
    var j:(Int, Int)->Int = {x, y -> x+y }
    println(j(1, 8))
 
也就是,函数也可以充当函数里面的参数,或者返回值
for循环
- kotlin也有swift中的开区间、闭区间的概念
四种类型:[],(),[),(] 
注意,所谓 “全开区间” 或者是 “左开右闭” 的区间,可以用其他两种方式代替
	var nums = 1..10
    for (num in nums){
        print("$num, ")
    }
    println()
    var nums2 = 1 until 10
    for (num in nums2){
        print("$num, ")
    }
 
运行结果:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1, 2, 3, 4, 5, 6, 7, 8, 9,
step n隔几个,打印1个
    for (num in 1..20 step 2){
        print("$num, ")
    }
 
运行结果:1, 3, 5, 7, 9, 11, 13, 15, 17, 19,
reversed()翻转打印
    var nums2 = 1 until 10
    for (num in nums2.reversed()){
        print("$num, ")
    }
 
运行结果:9, 8, 7, 6, 5, 4, 3, 2, 1,
list和map
使用listOf创建一个list
 使用witIndex()获取index的值,然后使用(x, y)两个参数接收
	fun main(args: Array<String>){
    var array = listOf<String>("1", "2", "4", "9")
    for ((i, e) in array.withIndex()){
        println("$i "+"$e")
    }
 
运行结果:
0 1
1 2
2 4
3 9
//导入TreeMap包
import java.util.TreeMap
fun main(args: Array<String>){
	//创建一个map
    var map2 = TreeMap<String, String>()
    //赋值
    map2["good"] = "好"
    map2["bad"] = "坏"
    map2["study"] = "学习"
    println(map2["bad"])
}
 
默认参数与具名参数
val PI = 3.14f
fun main(args: Array<String>){
    //要写3.14f,3.0f,而不是3.14,3
    var temp = circleArea(3.14f, 3.0f)
    var temp2 = circleArea(radius = 3.0f)
    println(temp)
    println(temp2)
}
//圆的面积
//默认Pi的值是PI
//通过在类型的后面添加 = 符号来设置参数的默认值。
fun circleArea(Pi: Float = PI, radius: Float): Float{
    return Pi*radius*2
}
 
readLine()
readLine():获取键盘输入的字,获取后是String?类型的
异常捕获try-catch
举个🌰:计算器
fun main(args: Array<String>){
    println("请输入第一个数字:")
    var a = readLine()
    while (a == null || a?.count() == 0){
        println("不能输入空值,请重新输入数字:")
        a = readLine()
    }
    println("请输入第二个数字:")
    var b = readLine()
    while (b == null || b?.count()==0){
        println("不能输入空值,请重新输入数字:")
        b = readLine()
    }
    try {
        var num1 = a!!.toInt()
        var num2 = b!!.toInt()
        var result = sum(num1, num2)
        println("$num1 + $num2 = $result")
    }catch (error: java.lang.Exception){
        println(error)
    }
}
fun sum(a: Int, b: Int):Int{
    return a+b
}
 
递归
举个例子:计算n的阶层
5的阶层 = 5 * 4 * 3 * 2 * 1 = 120
fun main(args: Array<String>){
    println(jieCeng(5))
}
fun jieCeng(a: Int):Int{
    //结束条件
    if (a == 1) return 1
    //递归计算
    return a * jieCeng(a-1)
}
 
尾递归计算
fun main(args: Array<String>){
    var result = 0
    println(add(100, result))
}
tailrec fun add(a: Int, result: Int):Int{
    println("计算机第${a}次计算, result=${result}")
    //结束条件
    if (a == 0) return 1
    //递归计算
    return add(a-1, result + a)
}
 
继承
- 如果想继承某个父类,则父类class前需要加
open,允许被继承 - 如果想重写父类的某个方法,则子类在同名方法前加
overrid,且父类在方法前加open,允许被重写 
接口和抽象类
- 接口是事物的能力,接口用的时候:接口名即可
 - 抽象类是事物的本质,抽象类用的时候:抽象类+()
 
代理和委托
A委托B去做某事情
 B代理A去做某事情
使用by 类名A(),就可以实现类名A里面的方法
	open class Father: IWashBowl by Son(){
    /**
    override fun wash() {
        println("我是爸爸,洗完一次10元")
    }
     * */
	}
//或者这样调用
open class Father: IWashBowl by Son(){
    override fun wash() {
        println("我是爸爸,我收了妈妈的10元")
        Son().wash()
        println("我是爸爸,我不洗碗,但是赚了9元")
    }
}
 
单例
创建类的时候,不使用class修饰,而且使用object修饰,则只有一份
印章类sealed
sealed:封闭的、密封的
- sealed class更在意类型
 - 枚举更在意数据
 
//跟enum类似,只有指定有限的类
sealed class Son {
    //记得加()
    class XXL(): Son()
    class XXM(): Son()
    fun sayHello(){
        println("hello")
    }
}
fun main(args: Array<String>){
    //记得加(),才是对象
    var son1:Son = Son.XXL()
    var son2:Son = Son.XXM()
    var son3:Son = Son.XXM()
    var house = listOf<Son>(son1, son2, son3)
    for (v in house){
        if(v is Son.XXM){
            v.sayHello()
        }
    }
}
 
函数式编程
fun main(args: Array<String>){
    var names = listOf<String>("tom", "locy", "jack")
    //forEach函数
    names.forEach(action = haha)
    //闭包,匿名函数
    names.forEach{
        a -> println(a)
    }
    //闭包
    names.forEach{
        //默认参数it
        println(it)
    }
}
//函数作为参数,前面使用var 参数名 =
//后面的函数名去掉
var haha = fun (name: String):Unit{
    println(name)
}
 
Kotlin高阶函数
一个函数,被用作参数或者返回值,则称为高阶函数
maxBy/minBy
找出数组array,里面age最大的item
 array.maxBy{a.age}
 找出数组array,里面height最小的item
 array.minBy{a.height}
返回的是item对象
var item: Object = array.maxBy{it.age}
 
filter
- 过滤找到特定条件的对象集合
好几个条件并列执行: 
var newArray = array.filter{
	(it.age>18) and (it.height>168) and (it.age<25)
}
 
map
- 把原数组某个属性,映射成新的集合
比如:把人群中的名字列出来,放入新的集合中 
var newArray = oldArray.map{
	"${it.name} : ${it.age}"
}
 
结果:{name1: 18, name2: 30, name3: 19}
any
- 是否有满足某个条件的对象
返回的是一个boolean值 
var temp: Boolean = array.any{
	it.age == 18
}
 
count
- 统计符合满足条件对象的个数
 
var count: Int = array.count{
	it.age<18
}
 
find
- 查找符合条件的对象,并返回第一个
 
var item: Object = array.finc{
	it.address=="北京"
}
 
groupBy
- 按照特征,把对象分为不同的组
 
var result: Array = array.groupBy{
	it.address
}
 
按照地址,把原来的数组,分别组成新的数组
DSL 领域特定语言
- 扩展函数
 - 中缀表达式
函数使用infix修饰后,.的操作,可以换成空格的操作 



















