扩展函数与属性
在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指针冲突的问题