Android开发(Kotlin) 泛型和委托
本文介绍了Kotlin中的泛型和委托机制。泛型部分包含泛型类和泛型方法的定义方式,以及通过上界限制泛型类型的方法,并展示了如何扩展函数使其适用于所有类。委托部分分为类委托和属性委托:类委托使用"by"关键字简化接口实现;属性委托通过Delegate类实现属性的getter/setter逻辑,文中还演示了如何自定义类似lazy的延迟初始化函数。这些特性可以有效减少样板代码,提高开
泛型
泛型主要有两种定义方式:一种是定义泛型类,另一种是定义泛型方法。
泛型类
class MyClass<T>{
fun method(param:T):T{
return param
}
}
泛型方法
class MyClass{
fun <T> method(param:T):T{
return param
}
}
对泛型的类型进行限制,将泛型上界设置为Number类型
class MyClass{
fun <T: Number> method(param:T):T{
return param
}
}
默认情况下,所有的泛型都是可以指定成可控类型的,泛型的默认上界是Any?。
将下面的函数,修改成可以作用在所有类上。
fun StringBuilder.build(block: StringBuilder.() -> Unit): StringBuilder{
block()
return this
}
fun <T> T.build(block: T.() -> Unit):T{
block()
return this
}
使用
SpannableStringBuilder().build {
append("123")
}
类委托和委托属性
类委托
委托是一种设计模式,基本理念:操作对象自己不会去处理某段逻辑,而是会把工作委托给另外一个辅助对象去处理。
kotlin有类委托和属性委托。
观察下面 这段代码,
class MySet<T>(val helperSet: HashSet<T>) : Set<T> {
override val size: Int
get() = helperSet.size
override fun contains(element: T): Boolean {
return helperSet.contains(element)
}
override fun containsAll(elements: Collection<T>): Boolean {
return helperSet.containsAll(elements)
}
override fun isEmpty(): Boolean {
return helperSet.isEmpty()
}
override fun iterator(): Iterator<T> {
return helperSet.iterator()
}
}
在上面set接口所实现的方法中,没有进行自己的实现,而是使用了辅助对象中相应的方法实现。
如果接口中待实现方法比较多,可以使用关键字by,只需在接口声明的后面是使用by关键字,再接上受委托的辅助对象,可以免去之前所写的一大堆模版式的代码。
class MySet<T>(val helperSet: HashSet<T>) : Set<T> by helperSet {
}
委托属性
委托属性的核心思想是将一个属性的具体实现委托给另一个类去完成。
委托属性的语法结构:
class MyClass {
var p by Delegate()
}
class Delegate {
var propValue: Any? = null
operator fun getValue(myClass: MyClass, prop: KProperty<*>): Any? {
return propValue
}
operator fun setValue(myClass: MyClass,prop: KProperty<*>,value: Any?){
propValue = value
}
}
这段代码表示p属性的具体实现委托给了Delegate 去完成。当调用p属性的时候会自动调用Delegate 类的getValue(),当p属性赋值的时候会自动调用Delegate 类的setValue()。
Delegate 类是标准的代码实现模版,在Delegate 类中我们必须实现getValue()和setValue()这两个方法,并且都得使用operator 关键字进行声明。
getValue(),第一个参数用于该Delegate 类的委托功能可以在什么类中使用;第二个参数可以用于获取各种属性相关值。
setValue(),最后一个参数表示具体要赋值给委托属性的值。
特殊情况,在Delegate 类中可以不用实现setValue()方法,让MyClass中的p属性使用val关键字声明。
实现一个自己的lazy函数
把想要延迟执行的代码放到by lazy代码块中,当变量首次被调用时,代码块才会执行。
val p by lazy{
}
lazy在这里只是一个高阶函数。
class Later<T>(val block: () -> T) {
}
在Later中实现getvalue方法。
class Later<T>(val block: () -> T) {
var value: Any? = null
operator fun getValue(any: Any?, property: KProperty<*>): T {
if (value == null) {
value = block();
}
return value as T
}
}
定义顶层函数
fun <T> later(block:() ->T) = Later(block)
使用
val p by later {
println("init")
val stringBuilder = StringBuilder()
stringBuilder.append("123")
stringBuilder
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
val binding = ActivityClickBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.clickButC.setOnClickListener {
println( p.toString())
}
}
执行结果,在没点击按钮的情况下,later 没有执行。点击按钮后懒加载执行。
2025-11-09 19:26:59.600 18511-18511 System.out com.bz.yh.xd.testkotlin I init
2025-11-09 19:26:59.600 18511-18511 System.out com.bz.yh.xd.testkotlin I 123
更多推荐
所有评论(0)