探究 Kotlin 類代理

Kotlin 實現類代理是經過 by 關鍵字,本文嘗試講解類代理在 Kotlin 的具體使用和實現原理。bash

首先,在一個自定義的 View 當中實現一個接口以下:ide

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 裏面仍是比較混亂。this

那應該怎麼辦呢?經過關鍵字 by 實現類代理優化代碼spa

class ArtboardView(context: Context): View(context), CanvasCapabilities by ArtboardCanvas()
複製代碼

代理類 ArtboardCanvas 直接實現 CanvasCapabilities 接口,不須要再實現內部定義 proxy 方式,代碼很是簡潔。代理

探究原理

經過反編譯成 Java 代碼發現原理很是簡單,Kotlin 並無作任何黑魔法,只是在內部再生成對應的 delegate 方法。code

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);
   }
}
複製代碼

這種方式實現,代碼很是簡潔。可是若是你有不少方法都須要實現,就會對應生成不少方法,可能會影響一些包大小。接口

拓展

構造函數傳入類代理ci

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")
    }
}
複製代碼

結論

當你遇到一些場景,類須要對外提供接口,以及須要實現多個接口,經過類代理這種方式抽取邏輯,能夠讓代碼很是簡潔。

相關文章
相關標籤/搜索