Kotlin 能够扩展一个类的新功能而无需继承该类或者使用像装饰者这样的设计模式,并且对被扩展的类代码本身不会造成任何影响。扩展函数可以为已经存在的类添加新的方法,并且不会修改原来的类。
例如,你可以为一个你不能修改的、来自第三方库中的类编写一个新的函数。 这个新增的函数就像那个原始类本来就有的函数一样,可以用普通的方法调用。 这种机制称为 扩展函数 。
也有 扩展属性 , 允许你为一个已经存在的类添加新的属性。
扩展是静态解析的
扩展不能真正的修改他们所扩展的类。通过定义一个扩展,你并没有在一个类中插入新成员, 仅仅是可以通过该类型的变量用点表达式去调用这个新函数。
我们想强调的是扩展函数是静态分发的,即他们不是根据接收者类型的虚方法。 这意味着调用的扩展函数是由函数调用所在的表达式的类型来决定的, 而不是由表达式运行时求值结果决定的。例如:
扩展函数
声明一个扩展函数,我们需要用一个 接收者类型 也就是被扩展的类型来作为他的前缀。
// String:表示要扩展的类
// toLenght:表示扩展函数的方法名
fun String.toLenght(): Int {
return length
}
//具体使用方法,等价于 "张山".length
"张山".tolenght()
fun String.pandding(count: Int, char: Char = '') : String {
val padding = (1 .. count).joinToString(""){ char.toString() }
return "${padding}${this}${padding}"
}
下面代码为 MutableList<Int>
添加一个swap
函数:
fun MutableList<Int>.swap(index1: Int, index2: Int) {
val tmp = this[index1] // “this”对应该列表
this[index1] = this[index2]
this[index2] = tmp
}
这个 this 关键字在扩展函数内部对应到接收者对象(传过来的在点符号前的对象) 现在,我们对任意 MutableList<Int>
调用该函数了:
val list = mutableListOf(1, 2, 3)
list.swap(0, 2) // “swap()”内部的“this”会保存“list”的值
当然,这个函数对任何 MutableList<T>
起作用,我们可以泛化它:
fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
val tmp = this[index1] // “this”对应该列表
this[index1] = this[index2]
this[index2] = tmp
}
为了在接收者类型表达式中使用泛型,我们要在函数名前声明泛型参数。
扩展方法的类型
fun String.times(count: Int): String {}
String::times (String, Int)->String
"**".times (Int)->String
扩展属性
与函数类似,Kotlin 支持扩展属性:
//自定义扩展属性,
var <T> MutableList<T>.lastData: T
get() = this[this.size - 1] //获取集合中最后一个对象
//设置集合中最后一个对象的值,如果上面定义的是val,则不能有set方法
set(value) {
this[this.size - 1] = value
}
具体用法,定义一个String类型的集合,然后通过lastData来改变或者获取集合中的最后一个对象
val strs = mutableListOf<String>()
strs.lastData = "dd"
var mo = strs.lastData
自定义扩展属性不能设置初始值,且主要是通过get,set方法来获取或者修改属性的值。
class PoorGuy {
var pocket: Double = 0.0 //如果这个属性是private的话,下面无法访问,必须是public的才行
}
var PoorGuy.moneyLeft: Double
get() {
return this.pocket
}
set(value) {
pocket = value
}
常用的扩展函数代码
//字符串转换成double
fun String.toDoubleNum(): Double {
return if (this.isNotEmpty()) {
try {
this.toDouble()
} catch (e: Exception) {
0.0
}
} else {
0.0
}
}
//字符串转换成Int
fun String.toIntNum(): Int {
return if (this.isNotEmpty()) {
try {
this.toInt()
} catch (e: Exception) {
0
}
} else {
0
}
}
//字符转换泛型对象
inline fun <reified T> String.toBean(): T {
return GsonUtils.toBean(this, T::class.java)
}
//拼接多个字符串设置给textView
fun TextView.setTexts(vararg strs: String) {
val strBuffer = StringBuffer()
for (str in strs) {
strBuffer.append(str)
}
this.text = strBuffer.toString()
}
//设置网络图片
fun ImageView.setImageUrl(url: Any, empty: Int) {
GlideUtils.showNormalCenterCropImage(url, this, empty)
}
//判断是否网络图片
fun String.isNetWorkImage(): Boolean {
return this.contains("http:/") || this.contains("https:/")
}
//中间toast
fun String.toastCenter() {
ToastUtils.setGravity(Gravity.CENTER, 0, 0)
ToastUtils.setBgColor(BaseLibraryApplication.getBaseApplication().resources.getColor(R.color.black_three))
ToastUtils.setMsgColor(BaseLibraryApplication.getBaseApplication().resources.getColor(R.color.white))
ToastUtils.showShort(this)
}
//底部toast
fun String.toastBottom() {
ToastUtils.setGravity(Gravity.BOTTOM, 0, 0)
ToastUtils.setBgColor(BaseLibraryApplication.getBaseApplication().resources.getColor(R.color.black_three))
ToastUtils.setMsgColor(BaseLibraryApplication.getBaseApplication().resources.getColor(R.color.white))
ToastUtils.showShort(this)
}
//qmuiTipDialog
fun String.showTipDialog(context: Context) {
val tipDialog = QMUITipDialog.Builder(context)
.setTipWord(this)
.create(true)
tipDialog.setCanceledOnTouchOutside(true)
tipDialog.show()
Timer().schedule(object : TimerTask() {
override fun run() {
tipDialog.dismiss()
}
}, 2000)
}
//修改文件名称
fun String.modifierFileName(): String {
var fileNames = this.split(".")
if (fileNames.size == 2) {
return fileNames[0] + TimeUtils.getNowMills() + "." + fileNames[fileNames.size - 1]
} else {
return this
}
}