扩展方法可以在不修改或继承原类的情况下给原类添加方法,当然扩展方法并不是真正的添加进了原类。
下面通过一个例子看看kotlin是怎么处理的。
将double format成常见的金钱格式:10000->10,000
fun Double.format2Money(): String {
val pattern = "###,###.##"
val df = DecimalFormat(pattern)
return df.format(this)
}
调用
val money = 10000.format2Money()
反编译成java:tools->Kotlin->Show Kotlin Bytecode->Decompile
public final class MoneyUtilsKt {
@NotNull
public static final String format2Money(double $receiver) {
String pattern = "###,###.##";
DecimalFormat df = new DecimalFormat(pattern);
String var10000 = df.format($receiver);
Intrinsics.checkExpressionValueIsNotNull(var10000, "df.format(this)");
return var10000;
}
}
kotlin生成了静态方法,将调用者当做参数$receiver传入该方法。和自己写的uitls也没啥分别。虽然是糖,但是用起来舒服。而且阅读性较强,还可以配合kotlin封装好的高阶函数使用。
给Activity添加dialog扩展函数
inline fun Activity.customDialog(block: AlertDialog.Builder.() -> Unit): AlertDialog =
AlertDialog.Builder(this)
.apply {
block()
}
.show()
inline fun Fragment.customDialog(block: AlertDialog.Builder.() -> Unit): AlertDialog =
AlertDialog.Builder(activity)
.apply {
block()
}
.show()
inline fun AlertDialog.Builder.positiveButton(
text: String = "确定",
crossinline block: (dialog: DialogInterface) -> Unit
) {
this.setPositiveButton(text) { dialog, _ ->
block(dialog)
}
}
inline fun AlertDialog.Builder.negativeButton(
text: String = "取消",
crossinline block: (dialog: DialogInterface) -> Unit
) {
this.setNegativeButton(text) { dialog, _ ->
block(dialog)
}
}
inline fun AlertDialog.Builder.neutralButton(
text: String = "知道了",
crossinline block: (dialog: DialogInterface) -> Unit
) {
this.setNeutralButton(text) { dialog, _ ->
block(dialog)
}
}
Activity中调用
customDialog {
setTitle("title")
setMessage("message")
positiveButton {
it.dismiss()
}
negativeButton {
it.dismiss()
}
neutralButton{
it.dismiss()
}
}
之前有分析过run函数,回看一下
public inline fun <T, R> T.run(block: T.() -> R): R {
return block()
}
kotlin封装的几个高阶函数是T类型的扩展方法,任何对象都可调用。
实战一下
inline fun <T> T.customDialog(block: AlertDialog.Builder.() -> Unit): AlertDialog =
AlertDialog.Builder(ActivityUtils.getTopActivity())
.apply {
block()
}
.show()
这里只是示范,不建议这样写。如果不需要调用者T,去掉泛型就是个普通的静态方法。
添加通用性较强的方法
inline fun <reified T> T.ktxLog(msg:String) = Log.d(T::class.java.name, msg)
简单说下关键字reified。inline方法中reified修饰泛型后,通过T::class.java拿到class对象,也就是具体化泛型。
网友评论