java 扩展属性,Kotlin的扩展属性和扩展方法

扩展方法的原理

Kotlin 中类的扩展方法并不是在原类的内部进行拓展,通过反编译为Java代码,可以发现,其原理是使用装饰模式,对源类实例的操作和包装,其实际相当于我们在 Java中定义的工具类方法,并且该工具类方法是使用调用者为第一个参数的,然后在工具方法中操作该调用者;

该调用者在Kotlin中使用this关键字表示;

比如:定义一个String的扩展方法,其中的this表示调用者本身;

fun String.times(t:Int){

val sb = StringBuilder()

for (i in 0 until t) {

sb.append(this)

}

println(sb.toString())

}

Kotlin中的调用方式: “aaaa”.times(10)

反编译为对应的Java代码:

public final class TestObjectKt {

public static final void times(@NotNull String $receiver, int t) {

Intrinsics.checkParameterIsNotNull($receiver, "$receiver");

StringBuilder sb = new StringBuilder();

IntRange var10000 = RangesKt.until(0, t);

int i = var10000.getFirst();

int var4 = var10000.getLast();

if(i <= var4) {

while(true) {

sb.append($receiver);

if(i == var4) {

break;

}

++i;

}

}

String var5 = sb.toString();

System.out.println(var5);

}

}

Java中的调用方式: TestObjectKt.times(“aaaa”,10);

可见Kotlin中实际是将调用者”aaaa”作为方法times的第一个参数;

扩展属性的原理

类的扩展属性原理其实与扩展方法是一样的,只是定义的形式不同,扩展属性必须定义get和set方法,并且类似于接口中定义的变量,没有 backingfield,即没有field关键字,不能用来存储变量。(一般的类属性,在其对象实例中都会分配一点内存来存储属性的值。)

fun main(args: Array) {

val str = "aa"

//没有backing field,不能存储值,其实际是通过setXXX(str,10)操作str

//输出:aa10

str.s = 10

//输出:2

println(str.s)

}

var String.s: Int

get() = this.length

set(value){

//set方法并没有field可以用来存储value,

//其实际作用是使用通过value来操作调用者,即this

println(this.plus(value))

}

对应的Java代码:

public final class ExtendsKt {

public static final void main(@NotNull String[] args) {

Intrinsics.checkParameterIsNotNull(args, "args");

String str = "aa";

setS(str, 10);

int var2 = getS(str);

System.out.println(var2);

}

public static final int getS(@NotNull String $receiver) {

Intrinsics.checkParameterIsNotNull($receiver, "$receiver");

return $receiver.length();

}

public static final void setS(@NotNull String $receiver, int value) {

Intrinsics.checkParameterIsNotNull($receiver, "$receiver");

String var2 = $receiver + value;

System.out.println(var2);

}

}

可以看出,为什么扩展属性会没有backing field,其实际仍然是工具方法,并不是在原类内部扩展。

扩展方法实现迭代遍历

实现了Iterable接口的类,可以使用for循环进行遍历;

通过扩展方法,类无需实现Iterator接口,即可实现被迭代;

fun ViewGroup.children() = object : Iterable {

override fun iterator() = object : Iterator {

var index = 0

override fun hasNext() = index < childCount

override fun next() = getChildAt(index++)

}

}

val views = // ...

for (view in views.children()) {

// TODO do something with view

}

val visibleHeight = views.children()

.filter { it.visibility == View.VISIBLE }

.sumBy { it.measuredHeight }

扩展ViewGroup属性获取ChildView

val ViewGroup.children: List

get() = (0..childCount -1).map { getChildAt(it) }

parent.children.forEach { it.visible() }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值