【KotlinとJava】委譲プロパティ

KotlinとJava

Javaでは外部のライブラリを使用しなければできなかったことがKotlinでは言語の機能として実装されているものがいくつかある。今回の委譲プロパティもその一つだ。

メンバー変数(プロパティ)への値の代入や取り出しを監視したいことはないだろうか?そんな要望もKotlinは快く受け入れてくれる。

今回は委譲プロパティの記述方法を紹介する。

Custom delegate.kt

import kotlin.reflect.KProperty

class Example {
    var p: String by Delegate()
    override fun toString() = "Example Class"
}

class Delegate() {
    operator fun getValue(thisRef: Any?, prop: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${prop.name}' to me!"
    }

    operator fun setValue(thisRef: Any?, prop: KProperty<*>, value: String) {
        println("$value has been assigned to ${prop.name} in $thisRef")
    }
}

fun main(args: Array<String>) {
    val e = Example()
    println(e.p)
    e.p = "NEW"
}

リンク

delegate property

メンバー変数(プロパティ)にデリゲートを設定することができる。値の代入と取り出しを別のクラスに委譲しているわけだ。パッケージのインポートを見るとわかるように、リフレクションを利用して機能を実現しているようだ。

override

ここでは中心の話題ではないが、関数のオーバーライドが登場したため、あわせて紹介しておこう。

override fun toString() = "Example Class"

の記述を省略せずに記述すると、次のようになる。

override fun toString(): String {
 return "Example Class"
}

ブロックを使わずに記述するほうは戻り値の型もreturnも必要ない。

Javaで記述

対比ができるようにJavaでも同じものを記述してみよう。

public class Example {  
  
    private String p;  
  
    public String getP()
        throws NoSuchFieldException {  
        return Delegate.getValue(this, this.getClass().getDeclaredField("p"));  
    }  
  
    public void setP(String value)
        throws NoSuchFieldException, IllegalAccessException {  
        Delegate.setValue(this, this.getClass().getDeclaredField("p"), value);  
    }  
  
    @Override  
    public String toString() {  
        return "Example Class";  
    }  
}

import java.lang.reflect.Field;
public class Delegate {  
  
    static String getValue(Object thisRef, Field prop) {  
        String template = "%s, thank you for delegating '%s' to me!";  
        return String.format(template, thisRef, prop.getName());  
    }  
  
    static void setValue(Object thisRef, Field prop, String value)
        throws IllegalAccessException {  
        // 値の代入  
        prop.setAccessible(true);  
        prop.set(thisRef, value);  
  
        String template = "%s has been assigned to %s in %s";  
        System.out.println(String.format(template, 
            value, prop.getName(), thisRef));  
    }  
}

public class Exp17 {  
    public static void main(String[] args)
        throws NoSuchFieldException, IllegalAccessException {  
        Example e = new Example();  
        System.out.println(e.getP());  
        e.setP("NEW");  
    }  
}

だいぶテクニカルなコードとなった。検査例外も多い。

コメント

このブログの人気の投稿

【KotlinとJava】分解宣言

wxPythonでのモーダルダイアログ作成

【Delphi Sample】並列プログラミング1