Kotlin进阶

时间:2021-7-3 作者:qvyue

1.次级构造

class CodeView : TextView {
 constructor(context: Context): super(context)
}

2.主构造器

class CodeView constructor(context: Context) : TextView(context)
// 如果没有被「可⻅性修饰符」「注解」标注,那么 `constructor` 可以省略
class CodeView (context: Context) : TextView(context)

成员变量初始化可以直接访问到主构造参数

class CodeView constructor(context: Context) : TextView(context){
 val color = context.getColor(R.color.white)
}

3.init 代码块

主构造不能包含任何的代码,初始化代码可以放到 init 代码块中

class CodeView constructor(context: Context) : TextView(context) {
 init {
 //...
 }
}

在初始化的时候,初始化块会按照它们在「⽂件中出现的顺序」执⾏。

class CodeView constructor(context: Context) : TextView(context) {
 init {
 // ...
 }
 val paint = Paint() // 会在 init{} 之后运⾏
}

4.构造属性

在主构造参数前⾯加上 var/val 使构造参数同时成为成员变量

class User constructor(var username: String?, var password: String?, var code:
String?)

5.data class

数据类同时会⽣⽣成

  • toString()
  • hashCode()
  • equals()
  • copy() (浅拷⻉)
  • componentN() …

6.相等性

  • == 结构相等(调用equals()比较)
  • === 引用(地址值)相等

7.解构

可以把⼀个对象「解构」成很多变量

val (code, message, body) = response

对应的java代码

val code = response.component1()
val message = response.component2()
val body = response.component3()

8.Elvis 操作符

可以通过 ?: 的操作来简化 if null 的操作

// lesson.date 为空时使⽤默认值
val date = lesson.date?: "⽇⽇期待定"
// lesson.state 为空时提前返回函数
val state = lesson.state?: return
// lesson.content 为空时抛出异常
val content = lesson.content ?: throw IllegalArgumentException("content
expected")

9.when操作符

when表达式可以接受返回值,多个分支相同的处理方式可以放在一起,用逗号分隔

val colorRes = when (lesson.state) {
 Lesson.State.PLAYBACK, null -> R.color.playback
 Lesson.State.LIVE -> R.color.live
 Lesson.State.WAIT -> R.color.wait
}

when 表达式可以⽤来取代 if-else-if 链。如果不提供参数,所有的分⽀条件都是布尔表达式

val colorRes = when {
 (lesson.state == Lesson.State.PLAYBACK) -> R.color.playback
 (lesson.state == null) -> R.color.playback
 (lesson.state == Lesson.State.LIVE) -> R.color.live
 (lesson.state == Lesson.State.WAIT) -> R.color.wait
 else -> R.color.playback
}

10.operator

通过 operator 修饰「特定函数名」的函数,例如 plus 、 get ,可以达到重载运算符的效果

11.lambda

如果函数的最后⼀个参数是 lambda ,那么 lambda 表达式可以放在圆括号之外:

lessons.forEach(){ lesson : Lesson ->
 // ...
}

如果你的函数传⼊参数只有⼀个 lambda 的话,那么⼩括号可以省略的:

lessons.forEach { lesson : Lesson ->
 // ...
}

如果 lambda 表达式只有⼀个参数,那么可以省略,通过隐式的 it 来访问

lessons.forEach { // it
 // ...
}

12.循环

通过标准函数 repeat() :

repeat(100) {
 //..
}

通过区间:

for (i in 0..99) {
}
// until 不包括右边界
for (i in 0 until 100) {
}

13.infix函数

必须是成员函数或扩展函数
必须只能接受⼀个参数,并且不能有默认值

// until() 函数的源码
public infix fun Int.until(to: Int): IntRange {
 if (to 

14.嵌套函数

Kotlin 中可以在函数中继续声明函数

fun func(){
 fun innerFunc(){

 }
}
  • 内部函数可以访问外部函数的参数
  • 每次调⽤时,会产⽣⼀个函数对象

15.函数简化

可以通过符号=简化原本直接return的函数

fun get(key :String) = SP.getString(key,null)

16.函数参数默认值

可以通过函数参数默认值来代替 Java 的函数重载

// 使⽤ @JvmOverloads 对 Java 暴露重载函数
@JvmOverloads
fun toast(text: CharSequence, duration: Int = Toast.LENGTH_SHORT) {
 Toast.makeText(this, text, duration).show()
}

17.扩展

  • 扩展函数可以为任何类添加上⼀个函数,从⽽代替⼯具类
  • 扩展函数和成员函数相同时,成员函数优先被调⽤
  • 扩展函数是静态解析的,在编译时就确定了调⽤函数(没有多态)

18.函数类型

函数类型由「传⼊参数类型」和「返回值类型」组成,⽤「 -> 」连接,传⼊参数需要⽤「 () 」,如果
返回值为 Unit 不能省略 函数类型实际是⼀个接⼝,我们传递函数的时候可以通过「 ::函数名 」,或者
「匿名函数」或者使⽤ 「 lambda 」

19.内联函数

  • 内联函数配合「函数类型」,可以减少「函数类型」⽣成的对象
  • 使⽤ inline 关键字声明的函数是「内联函数」,在「编译时」会将「内联函数」中的函数体直接插⼊到调⽤处。
  • 所以在写内联函数的时候需要注意,尽量将内联函数中的代码⾏数减少!

20.具体化的类型参数

因为内联函数的存在,我们可以通过配合 inline + reified 达到「真泛型」的效果

val RETROFIT = Retrofit.Builder()
 .baseUrl("https://api.hencoder.com/")
 .build()
inline fun  create(): T {
 return RETROFIT.create(T::class.java)
}
val api = create()

21.抽象属性

在 Kotlin 中,我们可以声明抽象属性,⼦类对抽象属性重写的时候需要重写对应的 setter/getter

22.属性委托

有些常⻅的属性操作,我们可以通过委托的方式,让它只实现一次,例如:

  • lazy延迟属性:值只在第一次访问的时候计算
  • observable可观察属性:属性发生改变时的通知
  • map集合:将属性存在一个map中
    对于一个只读属性(即val声明的),委托对象必须提供一个名为getValue()的函数
    对于一个可变属性(即 var 声明的),委托对象同时提供setValue()、getValue()函数

23.类委托

可以通过类委托的模式来减少继承类委托的,编译器会优先使用自身重写的函数,而不是委托对象的函数

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。