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<String>) {
    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<View> {
 override fun iterator() = object : Iterator<View> {
   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() }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容