还有一点大家注意一下,provideDelegate 这个方法的名称是不能随便起的,只能用这个名字,如果换了其它名字就会在 operator 关键字处报 'operator' modifier is inapplicable on this function: illegal function name;最后说明一下这段代码中用到的范型,ReadOnlyProperty<R, T> 要求传入两个范型,第一个范型 R 代表我们要 get 的属性所在类,第二个范型T代表我们要 get 的属性的类型
class ResourceID() {
val image_id: String = "101"
val text_id: String = "102"
}
class ResourceLoader(id: ResourceID) {
val d: ResourceID = id
operator fun provideDelegate( thisRef: MyUI, prop: KProperty ): ReadOnlyProperty {
if(checkProperty(thisRef, prop.name)){
return DellImpl(d)
}else{
throw Exception("Error ${prop.name}")
}
}
private fun checkProperty(thisRef: MyUI, name: String):Boolean {
if(name.equals("image") || name.equals("text")){
return true
}else{
return false
}
}
}
class DellImpl(d: ResourceID) : ReadOnlyProperty {
val id: ResourceID = d
override fun getValue(thisRef: MyUI, property: KProperty): String {
if(property.name.equals("image"))
return property.name+" "+id.image_id
else
return property.name+" "+id.text_id
}
}
fun bindResource(id: ResourceID): ResourceLoader {
var res = ResourceLoader(id);
return res
}
class MyUI {
val image by bindResource(ResourceID())
val text by bindResource(ResourceID())
//val webview by bindResource(ResourceID())
}
fun main(args: Array) {
try{
var ui = MyUI()
println(ui.image)
println(ui.text)
}catch(e: Exception) {
println(e.message)
}
}
2298Kotlin 泛型
关于星号投射,其实就是*代指了所有类型,相当于Any?
给文中补个例子方便理解:
class A<T>(val t: T, val t2 : T, val t3 : T)
class Apple(var name : String)
fun main(args: Array<String>) {
//使用类
val a1: A<*> = A(12, "String", Apple("苹果"))
val a2: A<Any?> = A(12, "String", Apple("苹果")) //和a1是一样的
val apple = a1.t3 //参数类型为Any
println(apple)
val apple2 = apple as Apple //强转成Apple类
println(apple2.name)
//使用数组
val l:ArrayList<*> = arrayListOf("String",1,1.2f,Apple("苹果"))
for (item in l){
println(item)
}
}
2297Kotlin 数据类与密封类
我的理解密封类就是一种专门用来配合 when 语句使用的类,举个例子,假如在 Android 中我们有一个 view,我们现在想通过 when 语句设置针对 view 进行两种操作:显示和隐藏,那么就可以这样做:
除此之外,如果 when 语句的分支不需要携带除“显示或隐藏view之外的其它信息”时(即只需要表明 when 语句分支,不需要携带额外数据时),用 object 关键字创建单例就可以了,并且此时 when 子句不需要使用 is 关键字。只有需要携带额外信息时才定义密封类的子类,而且使用了密封类就不需要使用 else 子句,每当我们多增加一个密封类的子类或单例,编译器就会在 when 语句中给出提示,可以在编译阶段就及时发现错误,这也是以往 switch-case 语句和枚举不具备的功能。
最后,我们甚至可以把这一组操作封装成一个函数,以便日后调用,如下:
// 先封装一个UI操作列表
class Ui(val uiOps: List = emptyList()) {
operator fun plus(uiOp: UiOp) = Ui(uiOps + uiOp)
}
// 定义一组操作
val ui = Ui() +
UiOp.Show +
UiOp.TranslateX(20f) +
UiOp.TranslateY(40f) +
UiOp.Hide
// 定义调用的函数
fun run(view: View, ui: Ui) {
ui.uiOps.forEach { execute(view, it) }
}
run(view, ui) // 最终调用
2301kotlin 委托
第一位那位老哥有些范型没写,我给他补上了(版本是 1.3)。
2300kotlin 委托
博主大神写的最后一个例子可能有点复杂,对我这样的小白来说可能不大好理解,我自己写一个简单点的例子,大家感受下:
最后输出:
如果觉得 MyReadOnlyPropertyImpl 这个类有点多余,也可以省去,直接在 MyProvider 类中返回匿名类对象:
怎么样,用匿名类是不是更直观能看出 println("do something") 是在 getValue 方法之外运行,假如 println("do something")这行代码就代表了博主所说的“检查属性一致性”的代码,那么这样做就实现了博主所说的“扩展所委托对象的逻辑,在创建属性时(而不仅在其 getter 或 setter 中)检查属性一致性”;
还有一点大家注意一下,provideDelegate 这个方法的名称是不能随便起的,只能用这个名字,如果换了其它名字就会在 operator 关键字处报 'operator' modifier is inapplicable on this function: illegal function name;最后说明一下这段代码中用到的范型,ReadOnlyProperty<R, T> 要求传入两个范型,第一个范型 R 代表我们要 get 的属性所在类,第二个范型T代表我们要 get 的属性的类型2299kotlin 委托
提供委托,在哪儿都没有完整的示例,试着自己补充完整,费了不少时间!分享出来后别人看了会说如此简单!或者说不对!不管怎么说,这份辛苦不能白费了,还是分享给大家。看了几家的文档,菜鸟的做得比较好!比较明白的人做的,受益匪浅,谢谢!
2298Kotlin 泛型
关于星号投射,其实就是*代指了所有类型,相当于Any?
给文中补个例子方便理解:
2297Kotlin 数据类与密封类
我的理解密封类就是一种专门用来配合 when 语句使用的类,举个例子,假如在 Android 中我们有一个 view,我们现在想通过 when 语句设置针对 view 进行两种操作:显示和隐藏,那么就可以这样做:
以上功能其实完全可以用枚举实现,但是如果我们现在想加两个操作:水平平移和纵向平移,并且还要携带一些数据,比如平移了多少距离,平移过程的动画类型等数据,用枚举显然就不太好办了,这时密封类的优势就可以发挥了,例如:
以上代码中,TranslateX 是一个类,它可以携带多于一个的信息,比如除了告诉 view 需要水平平移之外,还可以告诉 view 平移多少像素,甚至还可以告诉 view 平移的动画类型等信息,我想这大概就是密封类出现的意义吧。
除此之外,如果 when 语句的分支不需要携带除“显示或隐藏view之外的其它信息”时(即只需要表明 when 语句分支,不需要携带额外数据时),用 object 关键字创建单例就可以了,并且此时 when 子句不需要使用 is 关键字。只有需要携带额外信息时才定义密封类的子类,而且使用了密封类就不需要使用 else 子句,每当我们多增加一个密封类的子类或单例,编译器就会在 when 语句中给出提示,可以在编译阶段就及时发现错误,这也是以往 switch-case 语句和枚举不具备的功能。
最后,我们甚至可以把这一组操作封装成一个函数,以便日后调用,如下: