前言
本文簡要介紹代理模式在kotlin中的使用
手寫一個(gè)代理模式
定義一個(gè)接口中定義行走方法,并在坦克類中實(shí)現(xiàn)行走方法字支,而行走的具體方法則由實(shí)現(xiàn)了行走方法的代理類實(shí)現(xiàn)轨香。代碼如下
interface Moveable {
fun move();
}
class MoveProxy : Moveable {
override fun move() {
Log.e("move", "MoveProxy Moving")
}
}
class Tank : Moveable {
var proxy: MoveProxy;
override fun move() {
proxy.move()
}
constructor(proxy: MoveProxy) {
this.proxy = proxy;
}
}
val tank:Tank= Tank(MoveProxy())
tank.move()
測試結(jié)果
11-11 16:59:43.100 16068-16068/com.zhqy.javademo E/move: MoveProxy Moving
而我們也可以通過Kotlin中定義好的關(guān)鍵字by來實(shí)現(xiàn)上述功能
方法靜態(tài)代理的實(shí)現(xiàn)
interface Moveable {
fun move();
}
class MoveProxy : Moveable {
override fun move() {
Log.e("move", "MoveProxy Moving")
}
}
class Tank : Moveable by MoveProxy() {
}
測試結(jié)果
11-11 17:07:04.669 16274-16274/? E/move: MoveProxy Moving
從測試結(jié)果上來我們獲得了一樣的結(jié)果租漂,這是為什么呢
public final class Tank implements Moveable {
// $FF: synthetic field
private final MoveProxy $$delegate_0 = new MoveProxy();
public void move() {
this.$$delegate_0.move();
}
}
從Java字節(jié)碼中可以看了只要通過關(guān)鍵字By聲明我們實(shí)例化的一個(gè)代理類理盆,余下的工作都由kotlin來為我們實(shí)現(xiàn)。kotlin不僅僅能實(shí)現(xiàn)方法的靜態(tài)代理也能夠?qū)崿F(xiàn)屬性的靜態(tài)代理
屬性靜態(tài)代理的實(shí)現(xiàn)
下面一個(gè)例子實(shí)現(xiàn)對屬性name的獲取數(shù)據(jù)和設(shè)置數(shù)據(jù)時(shí)打印相關(guān)的數(shù)據(jù)
class Person(){
var name:String by MyDelegate()
}
//代理類
class MyDelegate{
//獲取屬性值的方法
/**
* person 實(shí)例對象
* property 屬性集合(包含修飾符倾剿,名稱等)
*/
operator fun getValue(person: Person, property: KProperty<*>): String {
Log.e("getValue","$person:${property.name}")
return ""
}
/**
* person 實(shí)例對象
* property 屬性集合(包含修飾符筷频,名稱等)
* s:設(shè)置的值
*/
//設(shè)置屬性值的方法
operator fun setValue(person: Person, property: KProperty<*>, s: String) {
Log.e("getValue","$person:${property.name}:$s")
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
var person=Person();
person.name="張三"
person.name
測是結(jié)果
11-11 17:23:24.271 17635-17635/? E/setValue: com.zhqy.javademo.Person@3157fe3:name:張三
11-11 17:23:24.271 17635-17635/? E/getValue: com.zhqy.javademo.Person@3157fe3:name
需要注意的是代理類需要實(shí)現(xiàn)以下兩個(gè)方法
/**
* person 實(shí)例對象
* property 屬性集合(包含修飾符,名稱等)
*/
operator fun getValue(person: Person, property: KProperty<*>): String {
Log.e("getValue","$person:${property.name}")
return ""
}
/**
* person 實(shí)例對象
* property 屬性集合(包含修飾符前痘,名稱等)
* s:設(shè)置的值
*/
//設(shè)置屬性值的方法
operator fun setValue(person: Person, property: KProperty<*>, s: String) {
Log.e("setValue","$person:${property.name}:$s")
}
Java字節(jié)碼如下
public final class Person {
// $FF: synthetic field
static final KProperty[] $$delegatedProperties = new KProperty[]{(KProperty)Reflection.mutableProperty1(new MutablePropertyReference1Impl(Reflection.getOrCreateKotlinClass(Person.class), "name", "getName()Ljava/lang/String;"))};
@NotNull
private final MyDelegate name$delegate = new MyDelegate();
@NotNull
public final String getName() {
return this.name$delegate.getValue(this, $$delegatedProperties[0]);
}
public final void setName(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.name$delegate.setValue(this, $$delegatedProperties[0], var1);
}
}
從字節(jié)碼中可以看到聲明了代理類MyDelegate的一個(gè)對象凛捏,并在get和set方法中分別調(diào)用了getVale和setValue方法實(shí)現(xiàn)代理功能。
當(dāng)然也可以使用關(guān)鍵字
class Person(){
var name:String by Delegate()
}
class Delegate(){
operator fun provideDelegate(person: Person, property: KProperty<*>):MyDelegate{
return MyDelegate()
}
}
//代理類
class MyDelegate{
//獲取屬性值的方法
/**
* person 實(shí)例對象
* property 屬性集合(包含修飾符芹缔,名稱等)
*/
operator fun getValue(person: Person, property: KProperty<*>): String {
Log.e("getValue","$person:${property.name}")
return ""
}
/**
* person 實(shí)例對象
* property 屬性集合(包含修飾符坯癣,名稱等)
* s:設(shè)置的值
*/
//設(shè)置屬性值的方法
operator fun setValue(person: Person, property: KProperty<*>, s: String) {
Log.e("setValue","$person:${property.name}:$s")
}
}
字節(jié)碼如下
// Person.java
package com.zhqy.javademo;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import kotlin.jvm.internal.MutablePropertyReference1Impl;
import kotlin.jvm.internal.Reflection;
import kotlin.reflect.KProperty;
import org.jetbrains.annotations.NotNull;
@Metadata(
mv = {1, 1, 10},
bv = {1, 0, 2},
k = 1,
d1 = {"\u0000\u0014\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\b\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002R+\u0010\u0005\u001a\u00020\u00042\u0006\u0010\u0003\u001a\u00020\u00048F@FX\u0086\u008e\u0002¢\u0006\u0012\n\u0004\b\n\u0010\u000b\u001a\u0004\b\u0006\u0010\u0007\"\u0004\b\b\u0010\t¨\u0006\f"},
d2 = {"Lcom/zhqy/javademo/Person;", "", "()V", "<set-?>", "", "name", "getName", "()Ljava/lang/String;", "setName", "(Ljava/lang/String;)V", "name$delegate", "Lcom/zhqy/javademo/MyDelegate;", "production sources for module app"}
)
public final class Person {
// $FF: synthetic field
static final KProperty[] $$delegatedProperties = new KProperty[]{(KProperty)Reflection.mutableProperty1(new MutablePropertyReference1Impl(Reflection.getOrCreateKotlinClass(Person.class), "name", "getName()Ljava/lang/String;"))};
@NotNull
private final MyDelegate name$delegate;
@NotNull
public final String getName() {
return this.name$delegate.getValue(this, $$delegatedProperties[0]);
}
public final void setName(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.name$delegate.setValue(this, $$delegatedProperties[0], var1);
}
public Person() {
this.name$delegate = (new Delegate()).provideDelegate(this, $$delegatedProperties[0]);
}
}
// Delegate.java
package com.zhqy.javademo;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import kotlin.reflect.KProperty;
import org.jetbrains.annotations.NotNull;
@Metadata(
mv = {1, 1, 10},
bv = {1, 0, 2},
k = 1,
d1 = {"\u0000\u001e\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u001d\u0010\u0003\u001a\u00020\u00042\u0006\u0010\u0005\u001a\u00020\u00062\n\u0010\u0007\u001a\u0006\u0012\u0002\b\u00030\bH\u0086\u0002¨\u0006\t"},
d2 = {"Lcom/zhqy/javademo/Delegate;", "", "()V", "provideDelegate", "Lcom/zhqy/javademo/MyDelegate;", "person", "Lcom/zhqy/javademo/Person;", "property", "Lkotlin/reflect/KProperty;", "production sources for module app"}
)
public final class Delegate {
@NotNull
public final MyDelegate provideDelegate(@NotNull Person person, @NotNull KProperty property) {
Intrinsics.checkParameterIsNotNull(person, "person");
Intrinsics.checkParameterIsNotNull(property, "property");
return new MyDelegate();
}
}
// MyDelegate.java
package com.zhqy.javademo;
import android.util.Log;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import kotlin.reflect.KProperty;
import org.jetbrains.annotations.NotNull;
@Metadata(
mv = {1, 1, 10},
bv = {1, 0, 2},
k = 1,
d1 = {"\u0000&\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0010\u0002\n\u0002\b\u0002\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u001d\u0010\u0003\u001a\u00020\u00042\u0006\u0010\u0005\u001a\u00020\u00062\n\u0010\u0007\u001a\u0006\u0012\u0002\b\u00030\bH\u0086\u0002J%\u0010\t\u001a\u00020\n2\u0006\u0010\u0005\u001a\u00020\u00062\n\u0010\u0007\u001a\u0006\u0012\u0002\b\u00030\b2\u0006\u0010\u000b\u001a\u00020\u0004H\u0086\u0002¨\u0006\f"},
d2 = {"Lcom/zhqy/javademo/MyDelegate;", "", "()V", "getValue", "", "person", "Lcom/zhqy/javademo/Person;", "property", "Lkotlin/reflect/KProperty;", "setValue", "", "s", "production sources for module app"}
)
public final class MyDelegate {
@NotNull
public final String getValue(@NotNull Person person, @NotNull KProperty property) {
Intrinsics.checkParameterIsNotNull(person, "person");
Intrinsics.checkParameterIsNotNull(property, "property");
Log.e("getValue", "" + person + ':' + property.getName());
return "";
}
public final void setValue(@NotNull Person person, @NotNull KProperty property, @NotNull String s) {
Intrinsics.checkParameterIsNotNull(person, "person");
Intrinsics.checkParameterIsNotNull(property, "property");
Intrinsics.checkParameterIsNotNull(s, "s");
Log.e("setValue", "" + person + ':' + property.getName() + ':' + s);
}
}
感覺就是從創(chuàng)建一個(gè)實(shí)例變成了通過provideDelegate獲取代理類對象
標(biāo)準(zhǔn)庫中的代理模式
除了自己實(shí)現(xiàn)代理類外,Kotlin標(biāo)準(zhǔn)庫中也未我們提供了一些實(shí)現(xiàn)好的代理模式最欠。
lazy:lazy關(guān)鍵字在調(diào)用響應(yīng)的屬性時(shí)才會會執(zhí)行響應(yīng)的代理方法示罗,并且該方法只會調(diào)用一次。
示例代碼如下
class Person(){
var name:String by Delegate()
val age by lazy{
Log.e("lazy","lazy")
18
};
}
var person=Person();
person.age
person.age
測試結(jié)果
11-11 17:49:15.047 18817-18817/com.zhqy.javademo E/lazy: lazy
從測試結(jié)果可以看出雖然調(diào)用了兩次 person.age芝硬,但lazy的函數(shù)體只執(zhí)行了一次
Delegates.observable:當(dāng)屬性值發(fā)生改變時(shí)會調(diào)用.
示例代碼如下
class Person(){
var name:String by Delegate()
val age by lazy{
Log.e("lazy","lazy")
18
};
var gender:String by Delegates.observable("男性"){
property, oldValue, newValue -> Log.e("onchange","${property.name}:$oldValue:$newValue")
}
}
var person=Person();
person.gender="女性"
測試結(jié)果如下
11-11 17:55:58.443 19182-19182/com.zhqy.javademo E/onchange: gender:男性:女性
其中property包含屬性的相關(guān)信息蚜点,oldValue是原先的屬性值,newValue為現(xiàn)在的屬性值拌阴。
by map:在類中尋找屬性名與Map<K,V>中key相同的再將數(shù)值賦給該屬性绍绘。
示例代碼如下
class Student( map:Map<String,Any>){
val name:String by map;
val age:Int by map
}
var map= mapOf<String,Any>("name" to "張三","age" to 18)
var student=Student(map)
Log.e("student","${student.name}:${student.age}")
測試結(jié)果
11-11 18:06:22.516 19482-19482/? E/student: 張三:18
以上就是本文的全部內(nèi)容