《Kotlin入门实战》CH6 | 扩展函数与扩展属性

字数 180阅读 20

扩展函数与属性

在Java中获取String中的第一个字符,StringUtil.firstChar(str)可能是这样写的,但是要想`"ABC".firstChar()是不可能的,因为Java中String是final类,在Kotlin中就不一样了。

1. 扩展函数

给String类中添加firstChar方法

fun String.firstChar(): String {
    if (this.length == 0) return ""
    else return this[0].toString()
}

fun main() {
    println("123".firstChar())  // 1
}

给List添加一个filter方法

fun <T> List<T>.Myfilter(f: (T) -> Boolean): List<T> {
    val result = ArrayList<T>().apply {
        this@Myfilter.forEach { 
            if (f(it)) add(it)
        }
    }
    return result
}

fun main() {
    val list = listOf<Int>(1, 2, 3, 4)
    println(list.Myfilter { it % 2 == 0 })
}

2. 扩展属性

var <T> MutableList<T>.firstElement: T
    get() {
        return this[0]
    }
    set(value) {
        this.set(0, value)
    }

fun main() {
    val list = listOf<Int>(1, 2, 3, 4)
    println((list as MutableList).firstElement)
}

3. 扩展的实现

把代码反编译成java代码,可以发现,拓展方法和属性都是被翻译成了静态的方法

public final class ImplementFunKt {
   @NotNull
   public static final String firstChar(@NotNull String $this$firstChar) {
      Intrinsics.checkParameterIsNotNull($this$firstChar, "$this$firstChar");
      return $this$firstChar.length() == 0 ?"":String.valueOf($this$firstChar.charAt(0));
   }
    
   public static final Object getFirstElement(@NotNull List $this$firstElement) {
      Intrinsics.checkParameterIsNotNull($this$firstElement, "$this$firstElement");
      return $this$firstElement.get(0);
   }

   public static final void setFirstElement(@NotNull List $this$firstElement, Object value) {
      Intrinsics.checkParameterIsNotNull($this$firstElement, "$this$firstElement");
      $this$firstElement.set(0, value);
   }
}

4.this冲突

如前面的filter函数中出现this冲突,

fun <T> List<T>.Myfilter(f: (T) -> Boolean): List<T> {
    val result = ArrayList<T>().apply {
        this@Myfilter.forEach {
            if (f(it)) add(it)
        }
    }
    return result
}

this会默认指向最内层对象,this@Myfilter就是使用限定符解决this指针冲突的问题

推荐阅读更多精彩内容