在Java中,我們要對一個類進行擴展方法,可以採用繼承該類新增方法。
Anim原有run方法:
class Anim {
protected String name;
Anim(String name) {
this.name = name;
}
protected void run() {
System.out.println("跑");
}
}
Dog繼承Anim類擴展eat方法:
class Dog extends Anim {
Dog(String name) {
super(name);
}
/**
* 擴展eat函數
*/
protected void eat() {
System.out.println("喫東西");
}
}
dog就擴展了eat方法:
var dog = Dog("旺財")
dog.run()
dog.eat()
在Kotlin中,我們可以使用擴展函數來新增方法
fun 被擴展類名.擴展函數名( 參數 ) {
//實現代碼
}
那麼,給Anim加一個擴展方法:
fun Anim.eat(food: String) {
println("喫$food")
}
Dog類繼承Anim,繼承了擴展函數eat(food: String),dog調用eat,打印“喫飯”
var dog = Dog("旺財")
dog.eat("飯")
在java中調kotlin擴展函數:Extends爲擴展函數文件名,
ExtendsKt.eat(Dog(), "飯");
如果擴展函數和被擴展類中的成員函數有相同的接收類型、名字和參數,那麼這種情況下總是取成員函數。
class Dog {
fun showName(){
print("Dog")
}
}
fun Dog.showName(){
print("Cat")
}
fun main(args: Array<String>) {
Dog().showName()
}
如果我們調用 Dog 類的 showName(),它將輸出“Dog”,而不是“Cat”。
擴展函數原理
對如下這個擴展函數進行反編譯:
fun String.first(num: Int): String {
return this.substring(0, num)
}
翻譯成的代碼:
public static final String first(@NotNull String $this$first, int num) {
Intrinsics.checkNotNullParameter($this$first, "$this$first");
byte var3 = 0;
boolean var4 = false;
String var10000 = $this$first.substring(var3, num);
Intrinsics.checkNotNullExpressionValue(var10000, "(this as java.lang.Strin…ing(startIndex, endIndex)");
return var10000;
}
編譯器會生成一個函數,傳入當前擴展類對象作爲第一個參數,在函數中對該對象進行一些列處理。
在項目中實際使用
在項目中,我們通常使用擴展函數用來代替Java中的Utils類。比如給Activity、TextView、ImageView、File、Context等類加擴展函數,以達到寫工具類的同等效果。
屏幕尺寸轉化擴展函數:
fun Context.dp2px(dpValue: Float): Int {
val scale = resources.displayMetrics.density
return (dpValue * scale + 0.5f).toInt()
}
fun Context.px2dp(pxValue: Float): Int {
val scale = resources.displayMetrics.density
return (pxValue / scale + 0.5f).toInt()
}
fun Context.sp2px(spValue: Float): Int {
val scale = resources.displayMetrics.scaledDensity
return (spValue * scale + 0.5f).toInt()
}
fun Context.px2sp(pxValue: Float): Int {
val scale = resources.displayMetrics.scaledDensity
return (pxValue / scale + 0.5f).toInt()
}
Activity顯示隱藏軟鍵盤擴展函數:
/**
* 顯示軟鍵盤
*/
fun Activity.showKeyboard() {
var imm: InputMethodManager = this.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
?: return
var view = this.currentFocus
if (view == null) {
view = View(this)
view!!.isFocusable = true
view!!.isFocusableInTouchMode = true
view!!.requestFocus()
}
imm.showSoftInput(view, InputMethodManager.SHOW_FORCED)
}
/**
* 隱藏軟鍵盤
*/
fun Activity.hideKeyboard() {
var imm: InputMethodManager = this.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
?: return
var view = this.currentFocus
if (view == null) {
view = View(this)
}
imm.hideSoftInputFromWindow(view.windowToken, 0)
}
文件操作擴展函數:
/**
* 存儲bitmap到本地
* @param bitmap
* @param file
* @return
*/
fun Bitmap.bitmapToFile(file: File): Boolean {
try {
if (!file.exists()) {
if (file.parentFile.exists()) file.createNewFile()
}
val out = FileOutputStream(file)
compress(Bitmap.CompressFormat.PNG, 100, out)
out.flush()
out.close()
return true
} catch (e: FileNotFoundException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
return false
}
/**
* 創建文件夾
*
* @param path
* @return
*/
fun String.mkDirs(): File {
val file = File(this)
if (!file.exists()) {
file.mkdirs()
}
return file
}