探究 Kotlin 类代理

作者: simpleeeeee | 来源:发表于2019-04-17 14:25 被阅读13次

Kotlin 实现类代理是通过 by 关键字,本文尝试讲解类代理在 Kotlin 的具体使用和实现原理。

首先,在一个自定义的 View 当中实现一个接口如下:

interface CanvasCapabilities {
    fun draw(circle: Circle)
    fun draw(rectangle: Rect)
}

class ArtboardView(context: Context): View(context), CanvasCapabilities

现在我们再创建 CanvasCapabilities 接口的实现:

class ArtboardCanvas: CanvasCapabilities {
    override fun draw(circle: Circle) = ...
    override fun draw(rectangle: Rect) = ...
}

这个时候,我们一般会使用接口代理方式实现我们的逻辑,比如:

class ArtboardView(context: Context): View(context), CanvasCapabalities {
    private val artboardCanvas = ArtboardCanvas() // proxy
    
    override fun draw(circle: Circle) = artboardCanvas.draw(circle)
    override fun draw(rectangle: Rect) = artboardCanvas.draw(rectangle)
}

这种方式实现,虽然逻辑已经和 View 分离开,但是 View 里面还是比较混乱。

那应该怎么办呢?通过关键字 by 实现类代理优化代码

class ArtboardView(context: Context): View(context), CanvasCapabilities by ArtboardCanvas()

代理类 ArtboardCanvas 直接实现 CanvasCapabilities 接口,不需要再实现内部定义 proxy 方式,代码非常简洁。

探究原理

通过反编译成 Java 代码发现原理非常简单,Kotlin 并没有做任何黑魔法,只是在内部再生成对应的 delegate 方法。

public final class ArtboardView extends View implements CanvasCapabilities {

   private final ArtboardCanvas $$delegate_0;

   public ArtboardView(@NotNull Context context) {
      Intrinsics.checkParameterIsNotNull(context, "context");
      super(context);
      this.$$delegate_0 = new ArtboardCanvas();
   }

   public void draw(@NotNull Rect rectangle) {
      Intrinsics.checkParameterIsNotNull(rectangle, "rectangle");
      this.$$delegate_0.draw(rectangle);
   }

   public void draw(@NotNull Circle circle) {
      Intrinsics.checkParameterIsNotNull(circle, "circle");
      this.$$delegate_0.draw(circle);
   }
}

这种方式实现,代码非常简洁。但是如果你有很多方法都需要实现,就会对应生成很多方法,可能会影响一些包大小。

拓展

构造函数传入类代理

class MySet(private val delegate: Set<Long> = HashSet()) : Set<Long> by delegate

实现多个类代理

class MySetMap : Set<Long> by HashSet(), Map<Long, Long> by HashMap() {
    override val size: Int
        get() = TODO("not implemented")

    override fun isEmpty(): Boolean {
        TODO("not implemented")
    }
}

结论

当你遇到一些场景,类需要对外提供接口,以及需要实现多个接口,通过类代理这种方式抽取逻辑,可以让代码非常简洁。

相关文章

  • 探究 Kotlin 类代理

    Kotlin 实现类代理是通过 by 关键字,本文尝试讲解类代理在 Kotlin 的具体使用和实现原理。 首先,在...

  • 深入理解属性代理

    前面我们一起探究了Kotlin对类代理的支持,深扒其实现及限制,见类代理就是这么简单。这一趟,我们来深入讨论下Ko...

  • kotlin-第三章(类与对象)

    构造函数 访问修饰符 伴生对象 单例类 动态代理 kotlin中特有的类 09:kotlin的构造函数 kotli...

  • 3.接口代理

    接口方法交给代理类实现 关键字 by 其中用kotlin接口代理,SeniorManager可以这样写

  • 深入分析Kotlin的属性代理机制

    前言 熟悉Kotlin的人可能知道,类代理是一种基于父类或者接口的实现,而在代理属性这边没有这种限制,而且这些代理...

  • 深入分析Kotlin的属性代理机制

    前言 熟悉Kotlin的人可能知道,类代理是一种基于父类或者接口的实现,而在代理属性这边没有这种限制,而且这些代理...

  • Kotlin中的类委托和属性委托

    Kotlin的委托可分为类委托和属性委托。 一、类委托 类委托是代理模式的应用,而代理模式可以作为继承的一个不错的...

  • Kotlin中的代理类

    前言 Kotlin是一种在Java虚拟机上运行的静态类型编程语言,被称之为Android世界的Swift,在Goo...

  • kotlin中的面相对象

    目录 抽象类与接口 多态和接口代理 kotlin中接口函数冲突问题 类及其成员的可见性 object(单例模式) ...

  • Kotlin中的面向对象详解

    目录 抽象类与接口 多态和接口代理 kotlin中接口函数冲突问题 类及其成员的可见性 object(单例模式) ...

网友评论

    本文标题:探究 Kotlin 类代理

    本文链接:https://www.haomeiwen.com/subject/hscnwqtx.html