【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");
}
}
だいぶテクニカルなコードとなった。検査例外も多い。
コメント
コメントを投稿