一、Kotlin基础

1.数据类型声明

在Kotlin中要定义一个变量需要使用var关键字

  1. //定义了一个可以修改的Int类型变量
  2. var number = 39

如果要定义一个常量可以使用val关键字,等价于Java的final关键字.

  1. val name = "miku"
  2. //给val定义的常量再次赋值就会提示错误
  3. name = "ミク"

在Kotlin中要声明一个数据类型必须要使用var或者val来定义.

2.数据类型

Kotlin的数据类型分为基本数据类型和引用数据类型.

基本数据类型:Boolean、Number、Char

引用类型:可空类型、Object、数组类型

Kotlin中的Number类型泛指所有跟数字有关的类型,int、float、double、long

  1. //java.lang.Integr Int--->int
  2. var intNumber:Number = 39
  3. //java.lang.Float Float--->float
  4. var floatNumber:Number = 39.0f
  5. //java.lang.Double Double--->double
  6. var doubleNumber:Number = 39.000000000000000
  7. //java.lang.Long Long--->long
  8. var longNumber:Number = 39L

2.1.Kotlin预定义的基本数据类型

  1. var intType:Int = 39 //int
  2. var shortType:Short = 39 //short
  3. var byteType:Byte = 0 //byte
  4. var boolType:Boolean = true //boolean
  5. var stringType:String = "miku" //String
  6. var floatType:Float = 39f //float
  7. var doubleType:Double = 39.0000000000 //double
  8. var longType:Long = 39L //long
  9. var numberType:Number = 39 //Integr、Float、Double、Long
  10. var charType:Char = '0' //char

字符串拼接,通过${}直接引用变量,不再需要引号 + 引号的方式

  1. val name = "komine"
  2. val text = "私の名前は${name}と申します。"
  3. print(text)

2.2.元组

元组是一个固定长度,且不能被修改的数据结构

  1. //二阶元组
  2. var person1 = Pair("komin",16)
  3. //三阶元组
  4. var person2 = Triple("komine",18,"女")
  5. person2.first //第一个元素的值
  6. person2.second //第二个元素的值
  7. person2.third //第三个元素的值

Kotlin的元组其实就是一个泛型对象的封装.通过反编译生成的.class文件可以看出,二阶元组其实是对应Pair类,

三阶元组其实是对应Triple类. first、second、third分别对应getFirst()、getSecond()、getThrid()方法.

如果用Java来实现的话差不多就是下面这个样子,可以看到,元组不过是Kotlin在源码阶段提供的一种更方便的语法而已.

  1. public class MyPair<First,Second> {
  2. private final First mFirstValue;
  3. private final Second mSecond;
  4. public MyPair(First first, Second second){
  5. this.mFirstValue = first;
  6. this.mSecond = second;
  7. }
  8. public First getFirst() {
  9. return mFirstValue;
  10. }
  11. public Second getSecond() {
  12. return mSecond;
  13. }
  14. }

2.3.可空类型

Kotlin定义了一种可以为空的数据类型,只有声明为可空类型的变量才能将null赋值于它.默认声明的类型全部都是非空类型.

  1. var str:String? = null //在类型的后面添加?表示该类型可空
  2. print(str?.length) //通过?.方式来访问可空类型的成员方法或变量,如果str是null则后面的调用会返回null,不会报错
  3. //如果你明确知道,str在某个时候肯定不为空,可以通过!!操作该变量,但如果str为空则会抛出空指针异常
  4. print(str!!.length)

2.4.数组

在Kotlin中定义一个数组非常简单.调用arrayOf()即可创建一个数组.

  1. var names = arrayOf("miku","rin","luka")
  2. var numbers = arrayOf(16,14,17)
  3. //跟Java一样,也可以通过[下标]的方式访问数组的元素
  4. print(names[0])
  5. //创建一个指定长度的数组,值为null
  6. var fixedArray = arrayOfNulls<Int>(39)
  7. //创建一个空数组
  8. var emptyArray = emptyArray<Int>()

2.5.集合

Kotlin的集合分为可变集合和不可变集合.可变集合都是由Mutable开头的.

可变集合

  1. //MutableList集合,该集合可以包含相同元素
  2. var mutableList = mutableListOf("miku","rin","luka")
  3. //键值对,包含Key和Value的集合
  4. var mutableMap = mutableMapOf<String,String>()
  5. var linkedHashMap = linkedMapOf<String,String>() //等价mutableMap
  6. //MutableSet集合,该集合不会出现相同的元素,如果集合已经包含某个值,添加的时候会忽略添加操作
  7. var mutableSet = mutableSetOf<Object>()
  8. var linkedSet = linkedSetOf<String>() //等价mutableSet

不可变集合

  1. //List集合,无法进行添加操作
  2. var list = listOf("miku","rin","luka")
  3. //Map集合,无法进行添加操作
  4. var map = mapOf(Pair("miku",16))
  5. var linkedMap =
  6. //Set集合,无法进行添加操作
  7. var set = setOf<Int>(0,1,2,3,4,5,6,7,8,9)

2.5.1扩展方法

toList() 返回一个不可变List集合

toMap() 返回一个不可变的Map集合

toSet() 返回一个不可变的Set集合

2.5.2集合操作

类似.Net中的Linq查询

any 判断集合中是否有满足条件的元素

  1. var mutableList = mutableListOf("miku","rin","luka")
  2. val result:Boolean = mutableList.any(){
  3. it == "miku" //有一个元素的值为miku
  4. }

all 判断集合中的所有元素是都否满足条件

  1. var mutableList = mutableListOf("miku","rin","luka")
  2. val result:Boolean = mutableList.all(){
  3. it.isNotEmpty() //元素的长度大于0
  4. }

none 判断集合中的所有元素是否都不满足条件,满足则返回true

  1. var mutableList = mutableListOf("miku","rin","luka")
  2. val result:Boolean = mutableList.none(){
  3. it.isNotEmpty() //元素的长度等于0 false
  4. }

count 返回满足条件的元素个数,类似sql中的select count(*) from table where xx = xx

  1. var mutableList = mutableListOf("miku","rin","luka")
  2. val result: Int = mutableList.count {
  3. it == "miku" //返回集合中元素值为miku的元素个数
  4. }

reduce 从第一个元素到最后一个元素的累加

  1. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  2. val result: Int = numbers.reduce() {
  3. sum: Int, i -> sum + i //sum:声明一个用于接收累加结果的变量 i->:循环每一个元素,sum + i:累加每个元素到sum
  4. }

reduceRight 从最后一个元素到第一个元素的累加

  1. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  2. val result: Int = numbers.reduceRight() {
  3. sum: Int, i -> sum + i
  4. }

fold 跟reduce类似,不过可以设置初始化,从初始值开始累加

  1. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  2. val result: Int = numbers.fold(10){
  3. sum, i -> sum + i
  4. }

foldRight...

sumOf 返回集合中所有元素的总和,该集合的元素必须是Number类型

  1. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  2. val result = numbers.sumOf{
  3. it
  4. }

dropWhile 去除满足条件的元素,直到不满足为止,返回剩余元素的集合

  1. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  2. val result = numbers.dropWhile {
  3. it < 5
  4. }

filter 过滤不满足条件的元素,返回满足元素的新集合

  1. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  2. val result = numbers.filter {
  3. it < 5
  4. }

filterNot 过滤满足条件的元素,返回不满足元素的新集合

  1. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  2. val result = numbers.filterNot {
  3. it < 5
  4. }

take 返回从第一个元素开始的N个元素

  1. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  2. val result = numbers.take(5) //{1,2,3,4,5}

takeLast 返回从最后一个元素开始的N个元素

...

takeWhile 返回从第一个元素开始符合给定条件的元素

  1. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  2. val result = numbers.takeWhile {
  3. it > 0
  4. }

drop 返回去掉N个元素之后的列表

  1. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  2. val result = numbers.drop(1)

dropLastWhile 返回从最后一个元素开始,去掉满足条件的元素

  1. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  2. val result = numbers.dropLastWhile {
  3. it > 5
  4. }

slice 保留指定下标对应的元素

  1. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  2. val result = numbers.slice(listOf(1,2,3))

map 将集合中的元素通过某种方法转换后,返回一个新集合

  1. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  2. val result = numbers.map {
  3. val diff = 10
  4. it * diff
  5. }

后续更新...

2.6.类型转换

Kotlin通过as关键字将一个类型转换为另一个类型.

  1. var numberType:Number = 39
  2. var intType:Int = numberType as Int

Kotlin可以通过 is 关键字自动完成装箱的操作.

  1. open class GameConsole{
  2. }
  3. class PS4 : GameConsole() {
  4. }
  5. class NintendoSwitch : GameConsole() {
  6. public val version = "10.0"
  7. }
  8. fun main(args: Array<String>) {
  9. val gameConsoles = arrayOf(PS4(),NintendoSwitch())
  10. val gameConsole = gameConsoles[1]
  11. //会自动完成装箱操作,在当前调用范围内将gameConsole识别NitendoSwitch,可以直接访问对象的成员,不需要手动转换
  12. if(gameConsole is NintendoSwitch){
  13. print(gameConsole.version)
  14. }
  15. }

3.运算符

Kotlin特有的运算符有===、!==

3.1.恒等和非恒等

判断两个对象之间的地址是否相等

  1. var obj1 = Object()
  2. var obj2 = Object()
  3. if(obj1 === obj2){
  4. println("恒等")
  5. }
  6. if(obj1 !== obj2){
  7. println("非恒等")
  8. }

3.2.位运算

只有Int和Long类型可以使用.

  1. val i:Int = 10
  2. val j:Int = 20
  3. val result = i shl j //有符号左移
  4. result = i shr j //有符号右移
  5. result = i ushr //无符号右移
  6. result = i and j //按位与
  7. result = i or j //按位或
  8. result = i xor //按位异或
  9. result = i inv j //按位取反

3.3.区间运算符

表示某个值是否在某个范围或者集合之中.

  1. //i >=0 && i <= 100
  2. if(i in 0..100){
  3. print(i)
  4. }

数组或者集合是否包含某个值

  1. val names = arrayOf("miku","rin","luka")
  2. if("miku" in names){
  3. print("包含")
  4. }

4.条件语句

when是Kotlin提供类似Java中Switch的条件语句.它能做到Switch能做到的所有事,并且还提供了更方便的语法.

  1. fun test(i:Int){
  2. when(i){
  3. // case 1
  4. 1 ->{
  5. }
  6. //case 2
  7. 2 -> {
  8. }
  9. //i >= 3 && i <= 9
  10. in 3..9 ->{
  11. }
  12. //default
  13. else ->{
  14. }
  15. }
  16. }

when如果不提供参数也可以当作if elseif使用

5.循环语句

跟Java的使用差别不大,一般配合区间运算符in来更简便的使用

  1. val names = arrayOf("miku","rin","luka")
  2. for (name in names){
  3. println(name)
  4. }
  5. //遍历数组或集合带索引
  6. for ((index,name) in names.withIndex()){
  7. }
  8. val i = 0
  9. for (i in 0..99){ //i = 0;i <= 99;i++
  10. println(i)
  11. }
  12. var i = 10
  13. while (i > 0){
  14. println(i)
  15. i--
  16. }
  17. do {
  18. i--
  19. println(i)
  20. }while (i > 0)
  21. //foreach
  22. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  23. numbers.forEach{ it ->
  24. println(it)
  25. }
  26. //foreach 带索引
  27. val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
  28. numbers.forEachIndexed{index, i ->
  29. println("index[${index}] = $i")
  30. }

6.函数

Kotlin中定义函数使用fun关键字.如果方法不需要返回值可以不写,或者写Unit

  1. fun sum(number1:Int,number2:Int):Int{
  2. return number1 + number2
  3. }

6.1默认参数

Kotlin中添加了默认参数的支持,当一个方法指定了参数的默认值,则调用的时候可以不提供该参数的值.

要使用默认参数,在参数的后面添加=进行赋值操作.

  1. fun sum(number1:Int,number2:Int = 0):Int{
  2. return number1 + number2
  3. }

6.2可变参数

和Java一样,Kotlin也提供可变参数的支持,使用vararg关键字声明可变参数

  1. fun sum(vararg number:Int){
  2. //number在使用的时候其实是一个数组类型的变量,可以调用数组的一些方法
  3. }

6.3Lambda表达式

Lambda表达式可以看作是一个匿名的函数.

  1. var execute:(Int,Int) -> Int = {x,y ->
  2. x * y
  3. }
  4. println(execute(10,10))

如果函数只有一个参数时可以省略不写,这个时候用it来表示

  1. var execute:(String) -> String = {
  2. it
  3. }
  4. println(execute("komine"))

6.4高阶函数

Kotlin支持将函数作为参数或者返回值,包含这样操作的函数称为高阶函数.将函数作为参数时使用双冒号::来传递.

  1. fun main(args: Array<String>) {
  2. call(::method)
  3. }
  4. fun call(m:(number:Int) -> Int){
  5. println(m(39))
  6. }
  7. fun method(number:Int):Int{
  8. return number * number
  9. }

也可以使用Lambda表达式来表示一个匿名参数.

  1. call{number: Int -> return@call number * number }

Kotlin本身也提供了一些高阶函数供我们使用,比如apply函数,在Android中初始化变量可以这样写.

  1. var paint = Paint().apply {
  2. this.isAntiAlias = true
  3. this.color = Color.BLACK
  4. this.style = Paint.Style.STROKE
  5. this.strokeWidth = 10f
  6. }

6.5内联函数

Kotlin支持内联函数,跟C++的内联函数作用一致,因为函数的执行有压栈和出栈的步骤,会带来一定的开销.

在将函数声明为内联函数的时候,在编译的时候,编译器会在所有调用函数的地方,将函数调用直接替换成函数体的内容.

一般来说,内联函数中的嵌套逻辑不能太复杂,C++的内联函数是否替换是由编译器决定的,Kotlin会按照inline关键直接替换.

通过反编译生成的class文件可以看到,内联函数就是直接将有函数调用的地方,直接替换成函数体的内容.

  1. fun main(args: Array<String>) {
  2. test()
  3. }
  4. inline fun test(){
  5. for (i in 0..99){
  6. println(i)
  7. }
  8. for (i in 0..99){
  9. println(i)
  10. }
  11. for (i in 0..99){
  12. println(i)
  13. }
  14. for (i in 0..99){
  15. println(i)
  16. }
  17. for (i in 0..99){
  18. println(i)
  19. }
  20. for (i in 0..99){
  21. println(i)
  22. }
  23. }

反编译结果

如果函数的参数中有函数参数类型或者Lambda表达式,也可以使用noinline关键字指定不参数内联的函数.

crossinline关键字待补充...

二、Kotlin进阶

1.协程

协程是跑在线程上的产物,它拥有自己的栈内存和局部变量,被称为轻量级Thread.它的内部实现是由编译器来完成的.

官方文档说明

在使用协程之前,需要添加依赖

  1. implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1'
  2. implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'

简单用法

  1. GlobalScope.launch(context = Dispatchers.Default, start = CoroutineStart.DEFAULT) {
  2. //延时1.5秒
  3. delay(1500L)
  4. println("当前线程:" + Thread.currentThread().name)
  5. println("World")
  6. }
  7. println("Hello,")
  8. println("当前线程:" + Thread.currentThread().name)
  9. Thread.sleep(3000L)

context:协程的上下文,这里设置的是CoroutineDispatch协程运行的线程调度器,它有四种线程模式:

Dispatchers.Default //默认

Dispatchers.IO //工作在其他线程

Dispatchers.Main //主线程

Dispatchers.Unconfined //不指定就是在当前线程,kotlinx.coroutines.DefaultExecutor

也可以自己创建一个协程上下文,这个上下文也可以理解为协程所运行在的线程.

  1. val context = newSingleThreadContext("single")

start:启动模式,默认是CoroutineStart.DEFAULT,就是创建之后就会启动

CoroutineStart.DEFAULT

CoroutineStart.ATOMIC

CoroutineStart.UNDISPATCHED

CoroutineStart.LAZY 懒加载模式,它会返回一个Job对象,你可以手动开启它.

  1. val job = GlobalScope.launch(context = Dispatchers.Default, start = CoroutineStart.LAZY) {
  2. //延时1秒
  3. delay(1500L)
  4. println("当前线程:" + Thread.currentThread().name)
  5. println("World")
  6. }
  7. println("Hello,")
  8. println("当前线程:" + Thread.currentThread().name)
  9. job.start()
  10. Thread.sleep(3000L)

GlobalScope.async 带返回值

  1. suspend fun main(args: Array<String>) {
  2. val result = GlobalScope.async {
  3. delay(1000L)
  4. return@async "async"
  5. }
  6. println(result.await())
  7. Thread.sleep(3000)
  8. }

async会阻塞当前协程,会等待当前协程执行完毕,调用await()的函数需要使用suspend关键字修饰.

协程的挂起,suspend表示当前协程被挂起.

  1. fun main(args: Array<String>) {
  2. GlobalScope.launch {
  3. //get方法是被suspend修饰的,表示调用时会将当前协程挂起
  4. val str = get()
  5. //会等待get()执行完毕才会继续执行
  6. printStr(str)
  7. }
  8. //防止进程结束
  9. Thread.sleep(3000L)
  10. }
  11. suspend fun get():String{
  12. println("get()正在执行..")
  13. delay(1000)
  14. return "data"
  15. }
  16. suspend fun printStr(str:String){
  17. println(str)
  18. }

协程之间也可以嵌套,调用await会阻塞外部协程,代码还是会按顺序运行

  1. fun main(args: Array<String>) {
  2. GlobalScope.launch {
  3. val str = GlobalScope.async {
  4. return@async get()
  5. }.await()
  6. GlobalScope.launch{
  7. printStr(str)
  8. }
  9. }
  10. //防止进程结束
  11. Thread.sleep(3000L)
  12. }
  13. suspend fun get():String{
  14. println("get()正在执行..")
  15. delay(1000)
  16. return "data"
  17. }
  18. suspend fun printStr(str:String){
  19. println(str)
  20. }

待补充...

2.面向对象

2.1类的声明

和很多语言一样,Kotlin使用class关键字来声明一个类.

  1. class Person{
  2. }

2.1.1内部类

  1. class Person{
  2. //内部类的声明使用inner关键字修饰
  3. inner class Info{
  4. }
  5. }

要实例内部类需要先实例化主类

  1. val person = Person("miku")
  2. val info = person.Info()

2.1.2数据类

通过data class 修饰的类称为数据类,数据类必须提供一个有参的构造函数.数据类一般不定义方法.

  1. data class MyData(val height:Float,val weight:Float,val money:Float){
  2. }

2.1.3枚举类

跟Java的枚举类使用基本相同.

  1. enum class DirectionEnum{
  2. East{
  3. override fun move() {
  4. //name:当前枚举常量的名称
  5. //ordinal:当前枚举常量的值
  6. println("name$name")
  7. println("value:$ordinal")
  8. }
  9. },
  10. South{
  11. override fun move() {
  12. }
  13. },
  14. West{
  15. override fun move() {
  16. }
  17. },
  18. North{
  19. override fun move() {
  20. }
  21. };
  22. abstract fun move();
  23. }

2.1.4密封类

emm...不知道怎么用,后面补充

2.1.5抽象类

使用abstract关键字声明一个抽象类

  1. open abstract class Person(name:String, age:Int){
  2. }

2.2构造函数

Kotlin的构造函数可以直接写在类名的后面,称为主构造函数,这样定义的构造函数是没有方法体的,要执行初始化操作

可以使用init代码块.

  1. open class Person(name:String, age:Int){
  2. init {
  3. println("主构造函数执行...")
  4. println("name:${name},age = $age")
  5. }
  6. }

2.2.1 副构造函数

通过constructor定义的构造函数称为副构造函数,需要间接调用主构造函数进行初始化

  1. fun main(args: Array<String>) {
  2. val person = Person("miku")
  3. }
  4. open class Person(name:String, age:Int){
  5. init {
  6. println("主构造函数执行...")
  7. println("name:${name},age = $age")
  8. }
  9. //副构造函数需要间接调用主构造函数通过this关键字
  10. constructor(name:String) : this(name,16) {
  11. println("副构造函数执行...")
  12. }
  13. }

2.2.2 构造函数私有化

如果不想类外部访问到类的构造函数,可以使用 private constructor来修饰主构造函数

  1. class ListDialog<T>private constructor(context: Context) :Dialog(context) {
  2. }

2.3继承

如果想让一个类可以被其他类继承,需要在类的声明之前加上open关键字,使用:冒号来继承

  1. open class Person{
  2. open fun sodayo(){}
  3. }
  4. class Student : Person() {
  5. }

如果子类想重写父类定义的方法,该方法必须是open关键字修饰的方法,抽象方法的修饰符默认是open.

2.4静态成员

Kotlin没有提供static关键字,如果想实现Java那样的静态成员调用可以使用companion object代码块来定义静态成员.

在Kotlin中称为伴生对象,用伴生对象的成员来代替静态成员.

  1. class PS4{
  2. companion object{
  3. val FIRMWARE_VERSION:Float = 10.0f
  4. fun boot(){
  5. println("boot...")
  6. }
  7. }
  8. }

跟Java一样,然后通过类名调用静态成员

  1. PS4.boot()
  2. PS4.FIRMWARE_VERSION

2.5接口

使用interface来声明一个接口.与Java的用法并无二致

  1. interface Callback{
  2. fun onSuccess()
  3. fun onFailed()
  4. }

3.泛型

基本使用和Java一致

  1. class Data<T>(private val data:T){
  2. fun get():T{
  3. return data
  4. }
  5. }
  1. val data1 = Data("String")
  2. println(data1.get())
  3. val data2 = Data(16)
  4. println(data2.get())

3.1out和in关键字

Kotlin中使用out和in来代替? extends 和? super使用,具体用法跟Java是类似的.

  1. fun main(){
  2. val ps4List = mutableListOf<PS4>()
  3. setGameConsoles(ps4List)
  4. val gameConsoles = getGameConsoles()
  5. for (gameConsole in gameConsoles){
  6. val ps4 = gameConsole as PS4
  7. ps4.play()
  8. }
  9. }
  10. // out ----> ? extends GamesConsole
  11. fun setGameConsoles(gamConsoles:MutableList<out GameConsole>){
  12. }
  13. //in -----> ? super PS4
  14. fun getGameConsoles():MutableList<in PS4>{
  15. val gameConsoles = mutableListOf<GameConsole>()
  16. gameConsoles.add(PS4())
  17. gameConsoles.add(PS4())
  18. return gameConsoles
  19. }
  20. open class GameConsole{
  21. open fun play(){
  22. }
  23. }
  24. class PS4 : GameConsole(){
  25. override fun play() {
  26. println("ps4 play...")
  27. }
  28. }
  29. class NintendoSwitch : GameConsole(){
  30. override fun play() {
  31. println("ns play...")
  32. }
  33. }

4.委托

其实就是代理设计模式.

4.1委托的使用场景

Java中的代理模式实现

  1. //支付接口
  2. public interface IPay {
  3. void pay();
  4. }
  5. //支付宝支付
  6. public class AliPay implements IPay{
  7. private float mMoney;
  8. public AliPay(float money){
  9. mMoney = money;
  10. }
  11. @Override
  12. public void pay() {
  13. Log.d("Alipay","支付宝支付" + mMoney + "元...");
  14. }
  15. }
  16. //微信支付
  17. public class WeChatPay implements IPay{
  18. private float mMoney;
  19. public WeChatPay(float money){
  20. mMoney = money;
  21. }
  22. @Override
  23. public void pay() {
  24. Log.d("WeChatPay","微信支付" + mMoney + "元...");
  25. }
  26. }
  27. //代理对象
  28. public class ProxyPay implements IPay{
  29. private IPay mPay;
  30. public ProxyPay(IPay pay){
  31. mPay = pay;
  32. }
  33. @Override
  34. public void pay() {
  35. mPay.pay();
  36. }
  37. }

Kotlin的代理模式实现

  1. interface IPay{
  2. fun pay()
  3. }
  4. class Alipay(private val money:Float) :IPay{
  5. override fun pay() {
  6. println("支付宝支付$money...")
  7. }
  8. }
  9. class WeChatPay(private val money: Float) :IPay{
  10. override fun pay() {
  11. println("微信支付$money...")
  12. }
  13. }
  14. class PayDelegate(private val play:IPay) :IPay by play{
  15. //什么都不需要做,系统帮我们完成一系列操作
  16. }

可以看出,Kotlin的委托其实就是简化了代理模式的实现过程.

4.2属性委托

将属性的赋值操作交给其他类来代理.可以通过其他类来统一控制属性的取值,合法性等等操作.

基本使用

  1. //声明一个接口,不一定要接口也可以是一个类
  2. interface IPropertyDelegate
  3. class PS4 :IPropertyDelegate{
  4. var version:String by DataDelegate()
  5. }
  6. class NintendoSwitch :IPropertyDelegate{
  7. var version:String by DataDelegate()
  8. }
  9. class DataDelegate {
  10. private var version:String = ""
  11. operator fun setValue(thisRef: IPropertyDelegate, property: KProperty<*>, value: String) {
  12. this.version = value
  13. }
  14. operator fun getValue(thisRef: IPropertyDelegate, property: KProperty<*>): String {
  15. return this.version
  16. }
  17. }

当给PS4或者NintendoSwitch对象的version赋值的时候,就会去到DataDelegate对象的setValue()方法,达到统一赋值的操作,相同的操作不需要在每个类都写一次

  1. val ps4 = PS4()
  2. ps4.version = "7.55"
  3. println(ps4.version)
  4. val ns = NintendoSwitch()
  5. ns.version = "13.0"
  6. println(ns.version)

5.其他

5.1扩展函数

给某个类添加一个扩展函数,其效果跟成员函数调用一致.一般定义到一个统一的文件中,不需要先定义一个类型,直接写就好

  1. //给String扩展了一个first方法
  2. fun String.first():Char{
  3. return this[0]
  4. }
  5. println("komine".first())

5.1扩展属性

给某个类添加一个扩展属性

  1. val Int.dp:Int
  2. get(){
  3. //简单模拟一下,开发中不是这么计算的
  4. return this * 1.5f.toInt()
  5. }

比如给Int类型添加了一个dp的扩展属性,可以将int值转换为对应的dp

  1. val width = 39.dp

待更新...

Kotlin快速上手的更多相关文章

  1. Java 程序员快速上手 Kotlin 11 招

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:霍丙乾 近经常会收到一些 "用 Kotlin 怎么写" 的问题,作为有经验的程序员, ...

  2. 快速上手 Kotlin 的 11 招

    本文转载自 Kotlin 公众号(KotlinX) 作者:bennyhuo 最近经常会收到一些 "用 Kotlin 怎么写" 的问题,作为有经验的程序员,我们已经掌握了一门或者多门 ...

  3. Java 程序员快速上手 Kotlin 11招

    收录待用,修改转载已取得腾讯云授权 作者 | 霍丙乾 编辑 | 迷鹿 前言 最近经常会收到一些 "用 Kotlin 怎么写" 的问题,作为有经验的程序员,我们已经掌握了一门或者多门 ...

  4. 【Python五篇慢慢弹】快速上手学python

    快速上手学python 作者:白宁超 2016年10月4日19:59:39 摘要:python语言俨然不算新技术,七八年前甚至更早已有很多人研习,只是没有现在流行罢了.之所以当下如此盛行,我想肯定是多 ...

  5. 快速上手Unity原生Json库

    现在新版的Unity(印象中是从5.3开始)已经提供了原生的Json库,以前一直使用LitJson,研究了一下Unity用的JsonUtility工具类的使用,发现使用还挺方便的,所以打算把项目中的J ...

  6. [译]:Xamarin.Android开发入门——Hello,Android Multiscreen快速上手

    原文链接:Hello, Android Multiscreen Quickstart. 译文链接:Hello,Android Multiscreen快速上手 本部分介绍利用Xamarin.Androi ...

  7. [译]:Xamarin.Android开发入门——Hello,Android快速上手

    返回索引目录 原文链接:Hello, Android_Quickstart. 译文链接:Xamarin.Android开发入门--Hello,Android快速上手 本部分介绍利用Xamarin开发A ...

  8. 快速上手seajs——简单易用Seajs

    快速上手seajs——简单易用Seajs   原文  http://www.cnblogs.com/xjchenhao/p/4021775.html 主题 SeaJS 简易手册 http://yslo ...

  9. Git版本控制Windows版快速上手

    说到版本控制,之前用过VSS,SVN,Git接触不久,感觉用着还行.写篇博文给大家分享一下使用Git的小经验,让大家对Git快速上手. 说白了Git就是一个控制版本的工具,其实没想象中的那么复杂,咱在 ...

随机推荐

  1. 推荐一款M1芯片电脑快速搭建集群的虚拟机软件

    虚拟机软件太多了,出名的莫过于VMware,VirutlaBox以及Parallels Desktop. 我们使用虚拟机软件一般有两种用途: 安装不同于宿主机系统的拥有用户界面的操作系统,比如Wind ...

  2. python小题目练习(七)

    题目:实现如下图所示结果 代码实现: """Author:mllContent:模拟火车订票系统Date:2020-11-16"""# 定义 ...

  3. Python实现中文字幕雨+源代码

    写在前面的一些P话: 最近浏览了很多关于用Python和Pygame实现代码雨的案例,发现很多都是没有深入讲解代码的整个实现过程,从0到1教会你制作中文文字雨. 然后在介绍的过程中,我也将深入介绍Py ...

  4. Codeforces Round #790 (Div. 4) A-H

    Codeforces Round #790 (Div. 4) A-H A 题目 https://codeforces.com/contest/1676/problem/A 题解 思路 知识点:模拟. ...

  5. CVPR 2017:See the Forest for the Trees: Joint Spatial and Temporal Recurrent Neural Networks for Video-based Person Re-identification

    [1] Z. Zhou, Y. Huang, W. Wang, L. Wang, T. Tan, Ieee, See the Forest for the Trees: Joint Spatial a ...

  6. PTA(BasicLevel)-1013 数素数

    一.问题描述 令 P​i​​ 表示第 i 个素数.现任给两个正整数 M≤N≤10​4​​,请输出 P​M​​ 到 P​N​​ 的所有素数. 输出格式:输入在一行中给出 M 和 N,其间以空格分隔. 输 ...

  7. 基于脑波眼电-语音-APP控制的多功能智能轮椅

    前言:这个项目是在2016-2017完成的,做的很浅显,贴出来与大家分享,希望能有帮助. 摘要 本项目主要是针对脑电信号控制的智能轮椅的设计,脑电控制是智能医疗领域的重要研究方向,旨在帮助行动不便但智 ...

  8. 广义径向基网络(RBF网络)

  9. Bash脚本debug攻略

    初学Bash时, 我从未想过想过bash也能debug, 也从未想过去debug Bash脚本. 随着技术的增长, 写的脚本越来越复杂, 使用echo打印日志来调试脚本的方式越来越捉襟见肘了. 直到某 ...

  10. 大事件回顾 | Eolink 5月重要动态速览!

    在春天和夏天中间悄然而至的 5 月刚刚过去,及时求变,在呼啸而过的时代中保持竞争力的 Eolink 最近又有哪些大动作呢?下面我们梳理了5月以来 Eolink 的重要动态,给大家提供阅览. 01 ** ...