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")
}
}
複製代碼
當你遇到一些場景,類須要對外提供接口,以及須要實現多個接口,經過類代理這種方式抽取邏輯,能夠讓代碼很是簡潔。