Kotlin擴展函數在項目中的使用

在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
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章