Kotlin 入门笔记04 | 青训营笔记

296 阅读1分钟

这是我参与「第四届青训营 」笔记创作活动的第13天

密封类

定义 Result 接口

 interface Result
 class Success(val msg: String) : Result
 class Failure(val error: Exception) : Result

写获取结果接口

 fun getResultMsg(result: Result) = when (result) {
     is Success -> result.msg
     is Failure -> result.error.message
     else -> throw IllegalArgumentException()
 }

这时存在两个问题,一个是不得不写 else 来通过编译,第二个是如果后续添加了新的 Result ,而没有在这里新增分支,执行时会抛出异常。

这时就可以使用密封类来指定该类的所有子类

 sealed class Result
 class Success(val msg: String) : Result()
 class Failure(val error: Exception) : Result()

此时可以不用 else, 如果新增了新的 Result 子类,编译器会直接报错,直到处理完所有可能的子类了,才能编译通过。

在安卓中应用

定义一个密封类MsgViewHolder,并让它继承自RecyclerView.ViewHolder,然后让LeftViewHolder和RightViewHolder继承自MsgViewHolder。这样就相当于密封类MsgViewHolder只有两个已知子类,因此在when语句中只要处理这两种情况的条件分支即可。

 sealed class MsgViewHolder(view: View) : RecyclerView.ViewHolder(view)
 class LeftViewHolder(view: View) : MsgViewHolder(view) {
     val leftMsg: TextView = view.findViewById(R.id.leftMsg)
 }
 class RightViewHolder(view: View) : MsgViewHolder(view) {
     val rightMsg: TextView = view.findViewById(R.id.rightMsg)
 }

扩展函数

用来给 final 类加扩展的函数

写法

 fun ClassName.methodName(param1: Int, param2: Int): Int {
     return 0
 }

比如给 String 类加扩展:新建一个 String.kt 文件

 fun String.lettersCount(): Int {
     var count = 0
     for (char in this) {
         if (char.isLetter()) {
             count++
         }
     }
     return count
 }

调用

 val count = "ABC123xyz!@#".lettersCount()

实际原理

实际上是生成了一个以该 final 类为参数的工具类(将字节码反编译成 Java 文件)

 public final class ExtendFuntionKt {
    public static final int lettersCount(@NotNull String $this$lettersCount) {
       Intrinsics.checkNotNullParameter($this$lettersCount, "$this$lettersCount");
       int count = 0;
       String var4 = $this$lettersCount;
       int var5 = $this$lettersCount.length();
 ​
       for(int var3 = 0; var3 < var5; ++var3) {
          char var2 = var4.charAt(var3);
          if (Character.isLetter(var2)) {
             ++count;
          }
       }
 ​
       return count;
    }
 }

应用

可以当成仅处理某一类对象的工具类来使用

运算符重载

Kotlin 的运算符重载是语法糖,会由编译器去替换成对应的函数

运算符重载使用的是operator关键字,只要在指定函数的前面加上operator关键字,就可以实现运算符重载的功能了。不同的运算符对应的函数不同。

以加号为例

 class Obj {
     operator fun plus(obj: Obj): [result] {
         // 处理相加的逻辑
     }
 }


对照表

表达式实际调用函数
a + ba.plus(b)
a - ba.minus(b)
a * ba.times(b)
a / ba.div(b)
a % ba.rem(b)
a++a.inc()
a--a.dec()
+aa.unaryPlus()
-aa.unaryMinus()
!aa.not()
a == ba.equals(b)
a > ba.compareTo(b)
a < ba.compareTo(b)
a >= ba.compareTo(b)
a <= ba.compareTo(b)
a..ba.rangeTo(b)
a[b]a.get(b)
a[b] = ca.set(b, c)
a in bb.contains(a)