├── 区间范围.md ├── 接口和类的修饰符.md ├── 1.png ├── 2.png ├── 3.png ├── 嵌套类和枚举类.md ├── 属性和字段.md ├── 去掉不必要的接口.md ├── 集合.md ├── 委托(代理).md ├── kotlin关键字.md ├── 泛型.md ├── 初识kotlin.md ├── 解构声明.md ├── 类和继承.md ├── README.md ├── 数据类和密封类.md ├── 函数和 Lambda 表达式.md └── 基础语法.md /区间范围.md: -------------------------------------------------------------------------------- 1 | ### 区间范围 2 | - 3 | -------------------------------------------------------------------------------- /接口和类的修饰符.md: -------------------------------------------------------------------------------- 1 | 2 | ## 接口和类的修饰符 3 | - 4 | -------------------------------------------------------------------------------- /1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/youxin11544/Kotlin-learning/HEAD/1.png -------------------------------------------------------------------------------- /2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/youxin11544/Kotlin-learning/HEAD/2.png -------------------------------------------------------------------------------- /3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/youxin11544/Kotlin-learning/HEAD/3.png -------------------------------------------------------------------------------- /嵌套类和枚举类.md: -------------------------------------------------------------------------------- 1 | ## 嵌套类和枚举类 2 | - [嵌套类](http://www.yiibai.com/kotlin/nested-classes.html) 3 | -------------------------------------------------------------------------------- /属性和字段.md: -------------------------------------------------------------------------------- 1 | # 属性和字段 2 | [属性和字段](https://www.kotlincn.net/docs/reference/properties.html) 3 | 4 | # 先说几个概念 5 | - 初始器、属性的访问器这个两个说的都是getter 和 setter 方法,翻译的问题。到底应该叫什么,我也不知道,反正知道意思就可以了 6 | - 幕后字段、后备字段这个两个说的field 这里有个坑,下面会介绍到 7 |   8 | ``` 9 | 10 | open class Person { 11 | var name: String = "adsf" 12 | get() { 13 | return field 14 | } 15 | set(value) { 16 |            this.name = value//这是错的 正确的应该是 field = value 17 |        } 18 | 19 | } 20 | 21 | ``` 22 | 23 | 24 | 对于 **field 标识符只能用在属性的访问器内。** 的理解:当我们访问 object.name = value的时候 25 | 实际是调用了该对象的set方法。field只能在get()set()方法中使用,get(),set()方法中只能用field标示符。 26 | -------------------------------------------------------------------------------- /去掉不必要的接口.md: -------------------------------------------------------------------------------- 1 | ### 去掉不必要的接口 2 | - kotlin的lambda 表达式和高阶函数可以为我们省去以前很多的java接口。下面的接口省掉了OnClickListenter这个接口 3 | 4 | ``` 5 | 6 | //简单改造view的setOnClickListenter 7 | class Main2Activity : AppCompatActivity() { 8 | override fun onCreate(savedInstanceState: Bundle?) { 9 | super.onCreate(savedInstanceState) 10 | setContentView(R.layout.activity_main2) 11 | var view = View() 12 | view.setOnClickListenter { 13 | it->it.toHome() 14 | } 15 | } 16 | } 17 | class View{ 18 | fun toHome() { 19 | 20 | } 21 | fun setOnClickListenter(listerner: (v:View) -> Unit) { 22 | listerner(this); 23 | } 24 | } 25 | 26 | ``` 27 | -------------------------------------------------------------------------------- /集合.md: -------------------------------------------------------------------------------- 1 | ## 集合 2 | - [集合](http://www.yiibai.com/kotlin/collections.html) 3 | - 分为可变和不可变,不可变前面都加上mutable。 listOf()、 mutableListOf()、 setOf()、 mutableSetOf()。 4 | - kotlin 关于集合的创建没有java一样的new ArrayList()都是靠函数去创建的。xxxxxof<>() 5 | - [惯用语法](http://www.yiibai.com/kotlin/idioms.html#只读-map) 6 | - 数组: var stations1= arrayOf("a","b","c","d")//常用的方式,它也有构造方法: 7 | 8 | ``` 9 | //创建一个有默认值的数组 Array(长度,{默认值}) 10 | var name=Array(20,{"默认值"}) 11 | for (s1 in name) { 12 | println(s1)//--->>默认值 默认值。。。。默认值 13 | } 14 |      //当然还可以更具不同的位置按照一定的逻辑和业务赋予不同的值,这个构造方法是高阶函数,可以接受lamber表达式 15 |       16 | 17 | ``` 18 | 19 | - 不可变集合的使用:暂时没有发觉很特别的用处,感觉和数组差不多。可变和不可变大概是想节约内存吧。 20 | 21 | 22 | -------------------------------------------------------------------------------- /委托(代理).md: -------------------------------------------------------------------------------- 1 | ## 委托(代理) 2 | - [代理](http://www.yiibai.com/kotlin/delegated-properties.html) 3 | 4 | 5 | ## (单例模式)懒汉式加载 6 | 7 | - Kotlin中的单例模式:Kotlin引入了一个叫做object的类型,用来很容易的实现单例模式,object类型的单例模式,本质上是饿汉式加载,即在类加载的时候创建单例。   它可能存在的问题有: 8 | 9 | ``` 10 | 11 | 1.如果构造方法中存在过多的处理,会导致加载这个类时比较慢,可能引起性能问题。 12 | 2.如果使用饿汉式的话,只进行了类的装载,并没有实质的调用,会造成资源的浪费。 13 | 14 | ``` 15 |     16 | 17 | ``` 18 | 19 | object SimpleSington { 20 | fun test() {} 21 | } 22 | //在Kotlin里调用 23 | SimpleSington.test() 24 | 25 | //在Java中调用 26 | SimpleSington.INSTANCE.test(); 27 | 28 | ``` 29 | 30 | - 针对饿汉式的潜在问题,我们可以使用懒汉式来解决,即将实例初始化放在开始使用之前。Kotlin版的懒汉式加载代码如下: 31 | 32 | 33 | ``` 34 | 35 | class LazySingleton private constructor(){ 36 | companion object { 37 | val instance: LazySingleton by lazy { LazySingleton() } 38 | } 39 | } 40 | //显式声明构造方法为private 41 | //companion object用来在class内部声明一个对象 42 | //LazySingleton的实例instance 通过lazy来实现懒汉式加载 43 | //lazy默认情况下是线程安全的,这就可以避免多个线程同时访问生成多个实例的问题 44 | ``` 45 | 46 | - lazy 的其他用法 47 | 48 | ``` 49 | 50 | private val defaultButton: Button by lazy { findViewById(R.id.default_number_picker_button) as Button } 51 | 52 | ``` 53 | -------------------------------------------------------------------------------- /kotlin关键字.md: -------------------------------------------------------------------------------- 1 | #Kotlin用到的关键字 2 | 3 | - var:定义变量 4 | - val:定义常量 5 | - fun:定义方法 6 | - Unit:默认方法返回值,类似于Java中的void,可以理解成返回没什么用的值 7 | - vararg:可变参数 8 | - $:字符串模板(取值) 9 | - 位运算符:or(按位或),and(按位与),shl(有符号左移),shr(有符号右移), 10 | - ushr(无符号右移),xor(按位异或),inv(按位取反) 11 | - in:在某个范围中 检查值是否在或不在(in/!in)范围内或集合中 12 | - downTo:递减,循环时可用,每次减1 13 | - step:步长,循环时可用,设置每次循环的增加或减少的量 14 | - when:Kotlin中增强版的switch,可以匹配值,范围,类型与参数 15 | - is:判断类型用,类似于Java中的instanceof()is运算符检查表达式是否是类型的实例。 如果一个不可变的局部变量或属性是指定类型,则不需要显式转换: 16 | 17 | - private //仅在同一个文件中可见 18 | - protected //同一个文件中或子类可见 19 | - public //所有调用的地方都可见 20 | - internal //同一个模块中可见 21 | 22 | - abstract //抽象类标示 23 | - final //标示类不可继承,默认属性 24 | - enum //标示类为枚举 25 | - open //类可继承,类默认是final的 26 | - annotation //注解类 27 | - init //主构造函数不能包含任何的代码。初始化的代码可以放到以 init 关键字作为前缀的初始化块(initializer blocks)中 28 | - field //field 标识符只能用在属性的访问器内。特别注意的是,get set方法中只能能使用filed 绝对的。属性访问器就是get set方法。洋气的名字。关于这个我会在后面详细说明 29 | - ://用于类的继承,变量的定义 30 | - .. //范围操作符(递增的) 1..5 2..6 千万不要6..2 31 | - :://作用域限定符,kotlin这个和c语言一样。这个我个人觉得在kotlin中还是很少见的。 32 | - inner //类可以标记为 inner {: .keyword } 以便能够访问外部类的成员。内部类会带有一个对外部类的对象的引用 33 | - object//对象声明 并且它总是在 object{: .keyword } 关键字后跟一个名称。对象表达式:在要创建一个继承自某个(或某些)类型的匿名类的对象会用到 34 | - it //单个参数的隐式名称 如果函数字面值只有一个参数,那么它的声明可以省略(连同 ->),其名称是 it。 35 | - inline //修饰符影响函数本身和传给它的 lambda 表达式:所有这些都将内联 36 | -------------------------------------------------------------------------------- /泛型.md: -------------------------------------------------------------------------------- 1 | ## Kotlin泛型 2 | - [泛型](http://www.yiibai.com/kotlin/generics.html) 3 | - 泛型约束:我们可以使用泛型约束来设定一个给定参数允许使用的类型,Kotlin 中使用 : 对泛型的的类型上限进行约束。最常见的约束是上界(upper bound), 默认的 上界是 Any? 4 | 5 | 6 | ``` 7 | 8 | //T就是上界 Comparable 的子类型可以替代 T 9 |  fun > sort(list: List) { 10 | // …… 11 | } 12 | 13 | ``` 14 | 15 | - 型变:Kotlin 中没有通配符类型,它有两个其他的东西:声明处型变与类型投影。 16 | - 声明处的类型变异使用协变注解修饰符:in、out,消费者 in, 生产者 out。 17 | 使用 out 使得一个类型参数协变,协变类型参数只能用作输出,可以作为返回值类型但是无法作为入参的类型 18 | - in 使得一个类型参数逆变,逆变类型参数只能用作输入,可以作为入参的类型但是无法作为返回值的类型 19 | - 类型投影:使用处型变 和 星投影,使用处型变就是在函数参数处使用型变来控制错误的发生。 20 | 21 | ## java泛型中的一些概念 22 | - java 中的通配符类型参数: ? extends E 23 | - 通配符表示包括E在内的所有子类,称为协变 24 | - 通配符表示包括E在内的所有父类,称为逆变 25 | - 协变: 表示包括E在内的所有子类,泛型对象只能读取,称为生产者 26 | - 逆变: 表示包括E在内的所有父类,泛型对象只能写入,称为消费者 27 | 28 | 29 | ## 星投影 30 | - Kotlin的泛型使用基本和Java一致 31 | - Java的 相当于 Kotlin的 ,Java的 相当于 Kotlin的 32 | - 只能生产(出参), 只能消费(入参) 33 | - 只能生产的原因是编译器无法确认什么对象符合那个未知的 T 的子类型,只知道一定返回T, 只能消费的原因是无法确认T超类的具体类型 34 | - <*>相当于java中的无泛型。对于 Foo ,其中 T 是一个具有上界的协变类型参数,Foo <*> 等价于 Foo ;对于 Foo ,其中 T 是一个逆变类型参数,Foo <*> 等价于 Foo 35 | - 先看下面的代码 36 | 37 | 38 | ``` 39 | 40 | class Book{ 41 | fun getType(a:T) { 42 | } 43 | 44 | fun getName() { 45 | 46 | } 47 | } 48 | open class Bar { 49 | fun getType():T?{ 50 | return null 51 | } 52 | } 53 | 54 | fun getType(a: Bar<*>,b:Book<*>) { 55 | val c = a.getType() 56 |    c.toString()// 这个时候c是Any的类型 57 |    b.getName() 58 |    b.getType( )//错误 ,括号里面无论传什么都是错的,也就是会所b的getType函数是不能使用的 59 | } 60 | 61 | ``` 62 | 63 | 在结合[泛型](http://www.yiibai.com/kotlin/generics.html)文档,就应该很快明白了。 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /初识kotlin.md: -------------------------------------------------------------------------------- 1 | #初识kotlin 2 | (中文可以叫 科特林) 3 | 4 | #关于Android studio怎么使用kotlin这点就不用介绍了(网上一大把),需要注意的是Android studio的版本是2.3.3以上 5 | [kotlin安装方法链接](http://www.cnblogs.com/duduhuo/p/6839990.html) 6 | 7 | #基本语法 8 | 1.三个关键字 9 | - var 声明**可变**的变量 10 | - val 声明**不可变**的变量,就想java中final修饰的字符串 11 | - fun kotlin声明函数前面需要加上fun关键字,不同于java但是前面的方法修饰public 这个是和java一样后面会讲到 12 | 13 | 2.了解编译器推断 14 | 类型转换是自动完成的,无论何时,编译器能够检测没有其它可选项,自动地完成类型转换。关于 编译器推断 这个很多文章再讲kotlin都会提到的。 15 | ``` 16 | val name = "youxin" 17 | val name2 :String = "youxin" 18 | //上面两个都是对的,因为kotlin会自动推断所以 :String 可以省略,不过我建议初学着还是加上好点,以后可以去掉,编译器在编译name的时候发觉后面给他赋值的是一个字符串,那么编译器就会推断他的类型是String 这就是编译器推断 19 | val z: View = findViewById(R.id.my_view) 20 | if (z is TextView) { 21 | z.setText ("I've been casted!") 22 | } 23 | //这里 z没有经过转型就可以使用 24 | ``` 25 | 再来看看下面的比较 26 | ``` 27 | //java 28 | public String getName(Object object) { 29 | if (object instanceof String) { 30 | return (String) object; 31 | } 32 | return null; 33 | } 34 | 35 | //kotlin 36 | fun getName(b:Any):String?{ 37 | if (b is String) { 38 | return b; 39 | } 40 | return null; 41 | } 42 | ``` 43 | 44 | #需要改变的观点 45 | 46 | 1. 在Kotlin中,所有都是对象,没有基本类型,没有void。如果有时没有返回值,实际时返回Unit对象。大多数情况下,Uint可以省略,但是它确实存在的,被隐藏了 47 | 因此,所有这些比哪里都是对象 48 | 49 | ``` 50 | 51 | val x: Int = 20 52 | val y: Double = 21.5 53 | val z: Unit = Unit 54 | ``` 55 | 56 | 57 | 2. 和Java一样,Kotlin也是基于JVM的,不同的是,后者是静态类型语言,意味着所有变量和表达式类型在编译时已确定。在Java中,通过装箱和拆箱在基本数据类型 和包装类型之间相互转换,而Kotlin中,所有变量的成员方法和属性都是对象。一些类型是Kotlin中内建,相当于创建的普通类,直接调用即可。 58 | 3. 在Kotlin源代码中,不管是常量还是变量在声明是都必须具有类型注释或者初始化。如果在声明时,进行了初始化,会自行推导其数据类型,以为着常量或者变量注 释类型。Kotlin中的数据类型包括数值类型、字符类型、布尔类型等。 59 | 4. 不同于Java的是,字符不属于数值类型。 在Kotlin中,字符类型不是基本数值类型,是一个独立的数据类型。 60 | 61 | 5. 在一些kotlin的教程中你会碰到很多穿插**块**这个字的一些文字,比如初始化块,代码块...。块理解成 {} 两个括号之间的代码,就像一整块代码一样。块说的   是代码。一行代码,代码块,初始化块...,这种语句以后自己要习惯。 62 | 6. 在 Kotlin 中类没有静态方法,取而代之的是kotlin的伴生对象 63 | 7. Kotlin 并没有 new 关键字 64 | -------------------------------------------------------------------------------- /解构声明.md: -------------------------------------------------------------------------------- 1 | ## 解构声明 2 | [解构声明](http://www.yiibai.com/kotlin/multi-declarations.html) 3 | 4 | ### 从函数中返回两个变量 5 | 6 | ``` 7 | 8 | class Main2Activity : AppCompatActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | setContentView(R.layout.activity_main2) 12 | var (province,city) = getData(2) 13 | Toast.makeText(this,province+"-"+city,Toast.LENGTH_LONG).show() 14 | } 15 | } 16 | 17 | fun getData(id:Int):Pair{ 18 | if (id < 5) { 19 | return "湖北" to "武汉" 20 | }else{ 21 | return "广东" to "深圳" 22 | } 23 | } 24 | 25 | ``` 26 | 27 | - 关于Pair和Triple的还有很多用法,需要自己慢慢体会,下面结合rxjava+Retrofit看看 28 | 29 | ``` 30 | 31 | class Main2Activity : AppCompatActivity() { 32 | override fun onCreate(savedInstanceState: Bundle?) { 33 | super.onCreate(savedInstanceState) 34 | setContentView(R.layout.activity_main2) 35 | 36 |        val a = requestType(1)//网络请求 书的类型 结合Retrofit 37 |        val b = requestName(2)//网络请求 书的名字 结合Retrofit 38 | Observable.zip(a, b, object : BiFunction> { 39 | override fun apply(t1: Int, t2: String): Pair { 40 |                return Pair("type", "name") //把数据整合到一起然后 通知观察者(订阅着) 41 |            } 42 | }).subscribe( 43 | { var (type, name) = it }, 44 | { Toast.makeText(this@Main2Activity,"onError"+ it.message,Toast.LENGTH_LONG).show() }, 45 | { Toast.makeText(this@Main2Activity,"onComplete",Toast.LENGTH_LONG).show() }) 46 | } 47 | } 48 | //结合Retrofit 我就不细写了 49 | fun requestType(a:Int):Observable{ 50 | val a = Observable.just(1) 51 | return a 52 | } 53 | fun requestName(a:Int):Observable{ 54 | val a = Observable.just("2") 55 | return a 56 | } 57 | 58 | ``` 59 | 60 | 61 | ### 在 lambda 表达式中解构 62 | - { a //-> …… } // 一个参数 63 | 64 | - { a, b //-> …… } // 两个参数 65 | 66 | - { (a, b) //-> …… } // 一个解构对 67 | 68 | - { (a, b), c //-> …… } // 一个解构对以及其他参数 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /类和继承.md: -------------------------------------------------------------------------------- 1 | ## 类和继承 2 | [类和继承-官网的介绍](https://www.kotlincn.net/docs/reference/classes.html) 3 | # 类可以包含 4 | - 构造函数和初始化块 5 | - 函数 6 | - 属性 7 | - 嵌套类和内部类 8 | - 对象声明 9 | 10 | ## 次构造函数 11 | - 关于主构和次构,最简单直观的差别就是主构是类头的一部分:它跟在类名(和可选的类型参数)后,而次构是在类体里面,先来看看下面的代码,看看它和java的区别.关于自己项目中java和kotlin 混编的项目可以自己先写个自己熟悉的java类,有些方法可以Android studio自己生成,然后在把这个类转成kotlin。比如自己有些时候突然忘记了一个语法,或者关键字,又或者其他的东西。(我是这么干的,如果大家有自己的更好的方法,当然更好了,至于如何将java类转成kotlin,自己Google很快就找到答案了) 12 | 13 | ``` 14 | //java 15 | public class MyTextView extends TextView { 16 | public MyTextView(Context context) { 17 | super(context); 18 | } 19 | public MyTextView(Context context, @Nullable AttributeSet attrs) { 20 | super(context, attrs); 21 | } 22 | public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 23 | super(context, attrs, defStyleAttr); 24 | } 25 | } 26 | //kotlin 27 | class MyTextView : TextView { 28 | constructor(context: Context) : super(context) {} 29 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {} 30 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {} 31 | } 32 | 33 | ``` 34 | 35 | 36 | ## 覆盖属性 37 |  关于覆盖属性只有一点需要注意的,先看下面代码 38 | ``` 39 | 40 | //父类 41 | open class YouXinB { 42 | open var x: Int? = null //属性x 43 | get() { 44 | //重写了get方法,此处后面详解 45 | field = 34 46 | return field 47 | } 48 | } 49 | //子类 50 | class YouXinA() : YouXinB() { 51 | override var x: Int?=null //它覆盖对应属性后,对应的方法也被覆盖 52 | 53 | 54 | } 55 | ``` 56 | 57 | - 对于Kotlin中的属性都有默认的get、set方法,当然也可以重写,比如上面的YouXinB的x的属性的get方法被重写了。但是YouXinA 覆盖属性后,TestB中定义的 get方法对其无效 58 | - 如果原类型为var,则覆盖类型可以为var,且不可以是val,如果原类型是val,覆盖类型可以是val,也可以是var 59 | 60 | 61 | 62 | 63 | ## 注意 64 | - Kotlin 并没有 new 关键字。 65 | - java的默认超类是Object,kotlin的默认超类是Any,当你在java中使用kotlin定义的类的对象,编译器会自动将kotlin中的Any转成Java中的object,反之在   kotlin中使用java定义创建的类的对象,编译器会自动将java中的object转成kotlin中的Any,看下面代码: 66 | 67 | ![2.png](https://github.com/youxin11544/Kotlin-learning/blob/master/2.png) 68 | 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kotlin-Simple 2 | Android开发从java到kotlin,本文是增对有java基础的人学习。下面的文章是我学习kotlin之后的理解,当然里面会有一点点是copy别人的描述,我主要重点是介绍看了一些别人的文章会后的理解以及一些不好理解的地方重点拿出来描述,直到理解透彻。关于某个定义我会直接给出我认为比较好的链接给大家去看,我就不在重复造轮子。**只讲些不一样的东西(比如一些用法,所以文档看着可能会觉得少,但是全是干货)**,当然肯定有写不足地方,大家可以随时吐槽。 3 | - [Kotlin官网-中文](https://www.kotlincn.net/) 4 | - [Kotlin官网-英语](https://kotlinlang.org/) 5 | - [huanglizhuo-github翻译的很好](https://github.com/huanglizhuo/kotlin-in-chinese) 6 | - [Kotlin教程链接](http://www.kotlindoc.cn/) 7 | - [入坑 Kotlin 开发前,这些项目能让你少走弯路](http://news.ifeng.com/a/20170825/51755041_0.shtml) 8 | 9 | 10 | 11 | 12 | 13 | 1.[初识kotlin](https://github.com/youxin11544/Kotlin-Simple/blob/master/%E5%88%9D%E8%AF%86kotlin.md) 14 | 15 | 2.[基础语法](https://github.com/youxin11544/Kotlin-Simple/blob/master/%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95.md) 16 | 17 | 3.[kotlin关键字](https://github.com/youxin11544/Kotlin-Simple/blob/master/kotlin%E5%85%B3%E9%94%AE%E5%AD%97.md) 18 | 19 | 4.[类和继承](https://github.com/youxin11544/Kotlin-learning/blob/master/%E5%B1%9E%E6%80%A7%E5%92%8C%E5%AD%97%E6%AE%B5.md) 20 | 21 | 5.[属性和字段](https://github.com/youxin11544/Kotlin-learning/blob/master/%E5%B1%9E%E6%80%A7%E5%92%8C%E5%AD%97%E6%AE%B5.md) 22 | 23 | 24 | 6.[数据类和密封类](https://github.com/youxin11544/Kotlin-learning/blob/master/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%92%8C%E5%AF%86%E5%B0%81%E7%B1%BB.md) 25 | 26 | 27 | 7.[泛型](https://github.com/youxin11544/Kotlin-learning/blob/master/%E6%B3%9B%E5%9E%8B.md) 28 | 29 | 30 | 8.[单例模式+委托(代理)](https://github.com/youxin11544/Kotlin-learning/blob/master/%E5%A7%94%E6%89%98(%E4%BB%A3%E7%90%86).md) 31 | 32 | 9.[函数和 Lambda 表达式,内联函数](https://github.com/youxin11544/Kotlin-learning/blob/master/%E5%87%BD%E6%95%B0%E5%92%8C%20Lambda%20%E8%A1%A8%E8%BE%BE%E5%BC%8F.md) 33 | 34 | 10.[解构声明](https://github.com/youxin11544/Kotlin-learning/blob/master/%E8%A7%A3%E6%9E%84%E5%A3%B0%E6%98%8E.md) 35 | 36 | 11.[集合 数组](https://github.com/youxin11544/Kotlin-learning/blob/master/%E9%9B%86%E5%90%88.md) 37 | 38 | 12.[区间/范围](https://github.com/youxin11544/Kotlin-learning/blob/master/%E5%8C%BA%E9%97%B4%E8%8C%83%E5%9B%B4.md) 39 | 40 | 13.[kotlin替换不必要的建造者模式](https://github.com/youxin11544/NumberPicker) 41 | 42 | 14.[kotlin替换不必要的接口](https://github.com/youxin11544/Kotlin-learning/blob/master/%E5%8E%BB%E6%8E%89%E4%B8%8D%E5%BF%85%E8%A6%81%E7%9A%84%E6%8E%A5%E5%8F%A3.md) 43 | 44 | 45 | -------------------------------------------------------------------------------- /数据类和密封类.md: -------------------------------------------------------------------------------- 1 | ## 数据类和密封类 2 | [数据类和密封类](https://www.kotlincn.net/docs/reference/data-classes.html) 3 | 4 | ## 扩展的作用域 5 | 当中没有讲到 接口、可见性修饰符、扩展方面的知识,因为这些知识对于作为已经撸了一两年的java的人来说,看这文档都很容易理解的 ,有点需要强调,文档中的一句话: 6 | **大多数时候我们在顶层定义扩展,即直接在包里** 7 | 这里就不说废话,直接举例看kotlin的源码来说。这个.kt文件在Kotlin包下面,他写了很多的扩展函数,没有定义类。 8 | 9 | ![源码](https://github.com/youxin11544/Kotlin-learning/blob/master/3.png) 10 | 11 | 12 | - kotlin源码中有很多这样的文件。我们自己在   写代码时也可以这样,比如一些工具呀,之前不是创建的工具类吗,其实可以不用创建工具类。还是看一个例子吧 13 | 14 | ``` 15 | 16 | package com.asdf.myapplication 17 | import android.os.Bundle 18 | import android.support.v7.app.AppCompatActivity 19 | import android.util.Log 20 | //导包 21 | import com.asdf.myapplication.test.isFilexists 22 | import com.asdf.myapplication.test.toast 23 | class Main2Activity : AppCompatActivity() { 24 | override fun onCreate(savedInstanceState: Bundle?) { 25 | super.onCreate(savedInstanceState) 26 | setContentView(R.layout.activity_main2) 27 | var c = "youxin".isFilexists() 28 |        var d = "youxin".toast(this).isFilexists()//是不是用起来很方便 怎么去使用就看个人了, 29 |        Log.e("youxin", c.toString()) 30 | Log.e("youxin", d.toString()) 31 | } 32 | } 33 | 34 | 35 | //下面就是我创建的一个工具文件 36 | package com.asdf.myapplication.test 37 | import android.content.Context 38 | import android.widget.Toast 39 | import java.io.File 40 | /** 41 | * Created by Administrator on 2017/9/19 0019. 42 | */ 43 | fun String.isFilexists(): Boolean { 44 | val dir = File(this) 45 | return dir.exists() 46 | } 47 | //这个 this 关键字在扩展函数内部对应到接收者对象(传过来的在点符号前的对象)这个应该不难理解吧。 48 | fun String.toast(context: Context):String { 49 | Toast.makeText(context,this,Toast.LENGTH_LONG).show() 50 | return this; 51 | } 52 | 53 | 54 | 55 | 56 | 57 | ``` 58 | 59 | 60 | 61 | ## 数据类 62 | - 这需要提一下的就是Android studio的一个插件叫JsonToKotlinClass 可以更具json转换成kotlin对应的data数据类,这插件和之前java里面的GsonFormat使用   方式有点微微的差别。 63 | - 注意点: 64 | 65 | ``` 66 | //这么写也没有错,但是我觉得还是不要这样做 67 | data class Che( 68 | var content_id: Int = 1, 69 | var title: String 70 | ) { 71 | var name: String = "adsf" 72 | } 73 | 74 | //下面看看 编译器编译这个之后的代码 75 | public final data class Che public constructor(content_id: kotlin.Int /* = compiled code */, title: kotlin.String) { 76 | public final var content_id: kotlin.Int /* compiled code */ 77 | 78 | public final var name: kotlin.String /* compiled code */ 79 | 80 | public final var title: kotlin.String /* compiled code */ 81 | 82 | public final operator fun component1(): kotlin.Int { /* compiled code */ } 83 | 84 | public final operator fun component2(): kotlin.String { /* compiled code */ } 85 | } 86 | // 其中的component只有两个 ,另外使用copy函数的时候name也会不在其中,所以我们还是按照标准写。至于这样写会不会有什么其他的用于,就不知道了。大家 87 | //如果发现了 可以告知下,相互学习 88 | 89 | ``` 90 | 91 | 92 | - 标准数据类,标准库提供了 Pair 和 Triple。这两个标注库太牛逼了,我们不能停留在简单的用法上面,它更好,更帅的用法,如何去使用后面会讲到。 93 | 94 | 95 | ## 密封类 96 | 97 | - [密封类](http://www.yiibai.com/kotlin/sealed-classes.html) 98 | - [枚举类](http://www.yiibai.com/kotlin/enum-classes.html) 99 | - 对于密封类可以理解为高级的枚举类,是枚举类的扩展。如果说你的枚举需要携带数据,这个密封类觉得完全符合你的要求 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /函数和 Lambda 表达式.md: -------------------------------------------------------------------------------- 1 | ## 函数和 Lambda 表达式 2 | - [Lambda 表达式](http://www.yiibai.com/kotlin/lambdas.html) 3 | - [内联函数](http://www.yiibai.com/kotlin/inline-functions.html#) 4 | ### 函数的中缀表示法 5 | [中缀表示法](http://www.yiibai.com/kotlin/functions.html) 6 | - 首先说它的使用条件: 7 |  - 他们是成员函数或扩展函数 8 | - 他们只有一个参数 9 | - 他们用 infix 关键字标注 10 | - 实际用法:我们先看看几个kotlin的源码 11 | 12 | 13 | ``` 14 | 15 | /** Shifts this value left by [bits]. */ 16 | public infix fun shl(bitCount: Int): Int 17 | /** Shifts this value right by [bits], filling the leftmost bits with copies of the sign bit. */ 18 | public infix fun shr(bitCount: Int): Int 19 | /** Shifts this value right by [bits], filling the leftmost bits with zeros. */ 20 | public infix fun ushr(bitCount: Int): Int 21 | 22 | 23 | /** 24 | * Creates a tuple of type [Pair] from this and [that]. 25 | * 26 | * This can be useful for creating [Map] literals with less noise, for example: 27 | * @sample samples.collections.Maps.Instantiation.mapFromPairs 28 | */ 29 | public infix fun A.to(that: B): Pair = Pair(this, that) 30 | 31 | 32 | /** 33 | * Returns a set containing all elements that are contained by both this set and the specified collection. 34 | * 35 | * The returned set preserves the element iteration order of the original collection. 36 | */ 37 | public infix fun Iterable.intersect(other: Iterable): Set { 38 | val set = this.toMutableSet() 39 | set.retainAll(other) 40 | return set 41 | } 42 | 43 | 44 | /** 45 | * Returns a progression from this value down to the specified [to] value with the step -1. 46 | * 47 | * The [to] value has to be less than this value. 48 | */ 49 | public infix fun Short.downTo(to: Short): IntProgression { 50 | return IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1) 51 | } 52 | 53 | ```` 54 | 55 | 从源码中可以看出 infix 的用法:当我们定义一个类的函数或者扩展函数的时候,如果这个函数接受的参数和自己是同一类的,并且又反回值那么就采用中缀表示法 56 | 57 | ### 高阶函数与 lambda 表达式 58 | [lambda 表达式](http://www.yiibai.com/kotlin/object-declarations.html) 59 | - 这节内容有的人可能有的学习起来会觉得有点难,其实只要转变一下观点记住下面的几点,就很简单了。看完后就可以愉快的看kotlin源码学习了。 60 | - 一个 lambda 表达式或匿名函数是一个“函数字面值(字面函数)”,即一个未声明的函数,做为表达式传递。 61 | - 函数类型:() -> T 62 | - kotlin 源码大量采用了lambda表达式,这样说明以后自己在写代码的时候,必然也会用到很多,这个也很简单,我们记住这点:将函数用作为参数或返回值的函数是   高阶函数,kotlin一般采用函数字面值(字面函数)的方式往高阶函数传参,一个高阶函数接受另一个lambda 表达式作为**最后一个参数**,lambda 表达式参数可以在 63 |  圆括号参数列表之外传递。 64 | - kotlin的lambda 表达式和高阶函数可以为我们省去以前很多的java接口。下面的接口省掉了OnClickListenter这个接口 65 | 66 | ``` 67 | 68 | //简单改造view的setOnClickListenter 69 | class Main2Activity : AppCompatActivity() { 70 | override fun onCreate(savedInstanceState: Bundle?) { 71 | super.onCreate(savedInstanceState) 72 | setContentView(R.layout.activity_main2) 73 | var view = View() 74 | view.setOnClickListenter { 75 | it->it.toHome() 76 | } 77 | } 78 | } 79 | class View{ 80 | fun toHome() { 81 | 82 | } 83 | fun setOnClickListenter(listerner: (v:View) -> Unit) { 84 | listerner(this); 85 | } 86 | } 87 | 88 | ``` 89 | 90 | 91 | 92 | - 接受者 是接受这个函数的对象,也就是调用这个函数的对象 93 | - 带接收者的函数字面值:可以调用该接收者对象上的方法而无需任何额外的限定符。这类似于扩展函数,它允你在函数体内访问接收者对象的成员。 94 |  可以这样理解,当我们在写一个高阶函数的时候,发觉需要用到lambda 表达式中参数对象里面的方法的时候,这个时候就用到带接收者的函数字面值。kotlin源码里 面很多这样的函数,下面举例说明: 95 | 96 | ``` 97 | 98 | /** 99 | * Calls the specified function [block] with the given [receiver] as its receiver and returns its result. 100 | */ 101 | @kotlin.internal.InlineOnly 102 | public inline fun with(receiver: T, block: T.() -> R): R = receiver.block() 103 | 104 | /** 105 | * Calls the specified function [block] with `this` value as its receiver and returns `this` value. 106 | */ 107 | @kotlin.internal.InlineOnly 108 | public inline fun T.apply(block: T.() -> Unit): T { block(); return this } 109 | 110 | /** 111 | * Calls the specified function [block] with `this` value as its argument and returns `this` value. 112 | */ 113 | @kotlin.internal.InlineOnly 114 | @SinceKotlin("1.1") 115 | public inline fun T.also(block: (T) -> Unit): T { block(this); return this } 116 | 117 | ``` 118 | 119 | 120 | 121 | 然而这里几个函数在我们项目中会经常用到,比如这样:现在有一本书,我要更具他现在的价格来分类,分完之,还要的得到这么书的名字 122 | 123 | 124 | ``` 125 | 126 | class Main2Activity : AppCompatActivity() { 127 | override fun onCreate(savedInstanceState: Bundle?) { 128 | super.onCreate(savedInstanceState) 129 | setContentView(R.layout.activity_main2) 130 | var book = Book() 131 | var name = book.apply { 132 | var price = getPrice() 133 | if (price < 50) { 134 |                Toast.makeText(this@Main2Activity,"小于50", Toast.LENGTH_LONG).show()//this@Main2Activity 是this表达式 135 |                type = "便宜书" 136 | }else{ 137 | Toast.makeText(this@Main2Activity,"大于50", Toast.LENGTH_LONG).show() 138 | type = "贵书" 139 | } 140 | }.getName() 141 | } 142 | } 143 | class Book{ 144 | var type:String? = null 145 | fun getName():String { 146 | return "youxin" 147 | } 148 | fun getPrice():Int { 149 | return 100 150 | } 151 | } 152 | 153 | ``` 154 | 155 | - 接受者 是接受这个函数的对象,也就是调用这个函数的对象 156 | - [this表达式](http://www.yiibai.com/kotlin/this-expressions.html)   157 | -------------------------------------------------------------------------------- /基础语法.md: -------------------------------------------------------------------------------- 1 | ## 基础语法 2 | [基础语法链接地址](http://blog.csdn.net/yubo_725/article/details/50758982) 3 | ## **定义包** 4 | 定义一个包这个和java一样就不多说了,那么哪里和java不同呢? 5 | ``` 6 | //java 7 | package com.asdf.myapplication.test; 8 | import android.widget.TextView; 9 | public class Student { 10 | public String getName(TextView textView) { 11 | return textView.getText().toString().trim(); 12 | } 13 | } 14 | 15 | //kotlin 16 | package com.asdf.myapplication.test 17 | import android.widget.TextView 18 | // 源文件可以从包声明开始 19 | fun getName():String { 20 | return "youxin" 21 | } 22 | fun TextView.name(name: String):Unit { 23 | this.text = name 24 | } 25 | class Person{ 26 | fun getName(textView: TextView?):String { 27 | return textView?.text as String; 28 | } 29 | } 30 | ``` 31 | 32 | **区别** kotlin 源文件可以从包声明开始(源文件就是代码,函数变量等等),java是不可以的 33 | 再来看看面的代码如何调用(关于 **?.** 和 **!!.** 后面会讲到) 34 | 35 | 36 | ``` 37 | 38 | //导包之后就可以调用了,属于同一个包下面就不用导包,这点和java一样的 39 |  import com.asdf.myapplication.test.Person 40 | import com.asdf.myapplication.test.getName 41 | class Main2Activity : AppCompatActivity() { 42 | var tv: TextView? = null 43 | override fun onCreate(savedInstanceState: Bundle?) { 44 | super.onCreate(savedInstanceState) 45 | setContentView(R.layout.activity_main2) 46 | tv = findViewById(R.id.youxin) as TextView 47 | getName() 48 | val person = Person() 49 | person.getName(tv); 50 | } 51 | } 52 | ``` 53 | 54 | 默认情况下,将多个软件包导入到每个Kotlin文件中:所以我们在用kotlin创建一个Acitivity之后会有很多的方法提议调用,不会像java一样使用list集合还要导包,然后利用kotlin的特性,源文件可以从包声明开始,那么这一下,我们的代码写法就变得非常的优雅。因为我们不需要在自己导包了,我们也不需要在方法名字前面加上包名了,就上上面的getName()方法一样。那么我这里想说的是kotlin默认导入的这些包中,包含的东西很多很多,并且都非常的实用。举几个例子 55 | 56 | - kotlin.* 57 | - kotlin.annotation.* 58 | - kotlin.collections.* 59 | - kotlin.comparisons.* (since 1.1) 60 | - kotlin.io.* 61 | - kotlin.ranges.* 62 | - kotlin.sequences.* 63 | - kotlin.text.* 64 | 65 | 看完下面的代码是不是有如高潮般的激动,listOf 和 mapOf 在kotlin.collections包下面,apply 和 with ,let 在kotlin包下面,还有一些我就不在举例了,我们也可以自己写,自己写也很简单,学完泛型,扩展,和高阶函数后就可以自由的玩耍了。 66 | 67 | ``` 68 | 69 | class Main2Activity : AppCompatActivity() { 70 | override fun onCreate(savedInstanceState: Bundle?) { 71 | super.onCreate(savedInstanceState) 72 | setContentView(R.layout.activity_main2) 73 | var aa = listOf(1,2,3) 74 | var bb = 1 to 2 75 | var cc = mapOf(bb,bb) 76 | var dd = mutableListOf("1","2","3") 77 | dd.map { 78 | //dosomething 79 | }.forEach { 80 | //dosomething 81 | } 82 | aa.apply { 83 | //dosomething 84 | }.apply { 85 | //dosomething 86 | } 87 | with("youixn"){ 88 | //dosomething 89 | }.let { 90 | //dosomething 91 | } 92 | 93 | } 94 | } 95 | 96 | ``` 97 | 98 | 这是部分的源码里面包含的东西还是蛮多的,包括一些api以后我们都会用的到 99 | 100 | ![image](https://raw.githubusercontent.com/youxin11544/Kotlin-learning/master/1.png) 101 | 102 | ## **定义属性** 103 | 格式是:**修饰符 关键字var或者val : 类型 **  这里的类型当后面赋值确定后是可以省略的,下面例子中的abstract 修饰的type 这里和java不同,需要特别注意下,public private···这和java一样,**?** 表示的意思是可以为空 104 | 105 | ``` 106 | 107 | public var name:String = "yoxin" 108 | private var name2 = "youxin2"//表示 name2 不能为空他是必须有值的 109 | protected var name3:String? = null//表示的是name3 可以为null也可以不为空 110 | public var id:Int = 1 111 | private var id2 = 2 112 | protected var id3:Int? = null 113 | 114 | abstract var type:String 115 | //abstract // 在自身不初始化,需要子类进行初始化,不能省略类型。 116 | ``` 117 | 118 | ## **定义函数** 119 | 关于函数的定义大家可以随便找一篇文章看看,这个简单,网上的文章都说的很好了。 120 | 121 | 1.具有返回Int类型的两个Int参数的函数: 122 | 123 | ``` 124 | 125 | fun sum(a: Int, b: Int): Int { 126 | return a + b 127 | } 128 | fun sum(a: Int, b: Int) = a + b 129 | //上面两种都是对的,因为kotlin可以自动 推断返回类型 130 | 131 | ``` 132 | 2.Unit为无类型:Unit 和 java的void 一样的意思 133 | ``` 134 | 135 | fun printSum(a: Int, b: Int): Unit { 136 | println("sum of $a and $b is ${a + b}") 137 | } 138 | fun printSum(a: Int, b: Int): Unit { 139 | println("sum of $a and $b is ${a + b}") 140 | } 141 | //上面两种都是对的,因为kotlin Unit返回类型可以省略: 142 | 143 | ``` 144 | ## **Kotlin的注释** 145 | 这个和java一样没什么好说的,Kotlin支持行尾和块注释,这个自己Google我是觉得可以忽略的,关于注释,保持和java一样就不会有什么问题 146 | 147 | 148 | ## **数据类型** 149 | 这个也没什么好说的,和java差不多的理解,但是有一些需要注意的,这里有一些介绍 150 | [初识kotlin](https://github.com/youxin11544/Kotlin-Simple/blob/master/%E5%88%9D%E8%AF%86kotlin.md) 151 | 每个数字类型都支持以下转换: 152 | - toByte(): Byte 153 | - toShort(): Short 154 | - toInt(): Int 155 | - toLong(): Long 156 | - toFloat(): Float 157 | - toDouble(): Double 158 | - toChar(): Char 159 | - 需要注意的是java是这么玩的:  Integer.parseInt("youxin") 160 | - 但是kotlin是这么玩的: "youxin".toInt(),其实kotlin的源码走的还是Integer.parseInt("youxin"),但是代码简单通俗易懂了。 161 | 162 | ## **条件和流程控制** 163 | 164 | - if表达式  含义这个和java一样 165 | 166 | ``` 167 | // 传统用法 168 | var max = a 169 | if (a < b) max = b 170 | // With else 171 | var max: Int 172 | if (a > b) { 173 | max = a 174 | } else { 175 | max = b 176 | } 177 | // 函数表达式 178 | val max = if (a > b) a else b 179 | 180 | ``` 181 | 182 | 183 | 184 | 185 | 186 | - When表达式 类似与java的Switch 187 | 188 | ``` 189 | 190 | when (x) { 191 | 1 -> print("x == 1") 192 | 2 -> print("x == 2") 193 | else -> { // Note the block 194 | print("x is neither 1 nor 2") 195 | } 196 | } 197 | 198 | when (x) { 199 | in 1..10 -> print("x is in the range") 200 | in validNumbers -> print("x is valid") 201 | !in 10..20 -> print("x is outside the range") 202 | else -> print("none of the above") 203 | } 204 | //in关键字 检查值是否在或不在范围内或集合中 205 | 206 | ``` 207 | 208 | - for循环 接受的参数是  变量 和 一个范围 使用in关键字 209 | 210 | ``` 211 | 212 | for(i in 1..10){ 213 | //i 214 | } 215 | // .. 表示从1到10的范围 216 | for (i in array.indices) { 217 | print(array[i]) 218 | } 219 | for ((index, value) in array.withIndex()) { 220 | println("the element at $index is $value") 221 | } 222 | ``` 223 | 224 | - while 循环 和java一样 225 | - 在循环中的 break 和 continue 语句 和java一样 226 | 227 | 228 | --------------------------------------------------------------------------------