常用到的幾個Kotlin開發技巧,減少對業務層代碼的入侵

語言: CN / TW / HK

highlight: vs theme: devui-blue


我正在參加「掘金·啟航計劃」

本篇文章主要介紹常用到的幾個kotlin開發技巧,能夠幫助我們減少對業務層代碼的修改,以及減少模板代碼的編寫。

善用@get/@set: JvmName()註解並搭配setter/getter使用

假設當前存在下面三個類代碼:

Opt1

```java public class Opt1 {

private String mContent;

public String getRealContent() {
    return mContent;
}

public void setContent(String mContent) {
    this.mContent = mContent;
}

} ```

Opt2

```java public class Opt2 {

public void opt2(Opt1 opt1) {
    System.out.println(opt1.getRealContent());
}

} ```

@Opt3 ```java public class Opt3 {

public void opt3(Opt1 opt1) {
    System.out.println(opt1.getRealContent());
}

} ```

這個時候我想將Opt1類重構成kotlin,我們先看下通過AS的命令Convert Java File to Kotlin File自動轉換的結果:

image.png

可以看到為了兼容Opt2Opt3的調用,直接把我的屬性名給改成了realContent,kotlin會自動生成getRealContent()setRealContent()方法,這樣Opt2Opt3就不用進行任何調整了,kotlin這樣就顯得太過於智能了。

這樣看起來沒啥問題,但是java重構kotlin,直接把屬性名給我改了,並隱式生成了屬性的set和get方法,對於java而言不使用的方法會報灰提示或者只有當前類使用AS會警告可以聲明成private,但是對於kotlin生成的set、get方法是隱式的,容易忽略。

所以大家在使用Convert Java File to Kotlin File命令將java重構kotlin的結果一定不能抱有百分之百的信任,即使它很智能,但還是一定要細細的看下轉換後的代碼邏輯,可能還有不少的優化空間。

這個地方就得需要我們手動進行修改了,比如不想對外暴露修改這個字段的set方法,調整如下:

kotlin class Opt1 { var realContent: String? = null private set }

再比如保持原有的字段名mContent,不能被改為realContent,同時又要保證兼容Opt2Opt3類的調用不能報錯,且儘量避免去修改裏面的代碼,我們就可以做如下調整:

kotlin class Opt1 { @get: JvmName("getRealContent") var mContent: String? = null private set }

善用默認參數+@JvmOverloads減少模板代碼編寫

假設當前Opt1有下面的方法:

java public String getSqlCmd(String table) { return "select * from " + table; }

且被Opt2Opt3進行了調用,這個時候如果有另一個類Opt3想要調用這個函數並只想從數據庫查詢指定字段,如果用java實現有兩種方式:

  1. 直接在getSqlCmd()方法中添加一個查詢字段參數,如果傳入的值為null,就查詢所有的字段,否則就查詢指定字段:

java public String getSqlCmd(String table, String name) { if (TextUtils.isEmpty(name)) { return "select * from " + table; } return "select " + name + " from " + table; }

這樣一來,是不是原本Opt2Opt3getSqlCmd()方法調用是不是需要改動,多傳一個參數給方法,而在日常的項目開發中,有可能這個getSqlCmd()被幾十個地方調用,難道你一個個的改過去?不太現實且是一種非常糟糕的實現。

  1. 直接在Opt1中新增一個getSqlCmd()的重載方法,傳入指定的字段去查詢:

java public String getSqlCmd(String table,String name) { return "select " + name + " from " + table; }

這樣做的好處就是不用調整Opt2Opt3getSqlCmd(String table)方法調用邏輯,但是會編寫很多模板代碼,尤其是getSqlCmd()這個方法體可能七八十行的情況下。

如果Opt1類代碼減少即200-400行且不負責的情況下,我們可以將其重構成kotlin,藉助於默認參數來實現方法功能增加又不用編寫模板代碼的效果(如果你的Java類上千行又很複雜,請謹慎轉換成kotlin使用下面這種方式)。

kotlin @JvmOverloads fun getSqlCmd(table: String, name: String? = null): String { return "select ${if (name.isNullOrEmpty()) "*" else name} from $table" }

添加默認參數name時還要添加@JvmOverloads註解,這樣是為了保證java只傳一個table參數也能正常調用。

通過上面這種方式,我們就能保證實現了方法功能增加,又不用改動Opt2Opt3對於getSqlCmd()方法的調用邏輯,並且還不用編寫額外的模板代碼,一舉多得。

總結

本篇文章主要介紹了在java重構成kotlin過程中比較常用到的兩個技巧,最終實現效果是減少對業務邏輯代碼的入侵,希望能對你有所幫助。