常用到的幾個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過程中比較常用到的兩個技巧,最終實現效果是減少對業務邏輯程式碼的入侵,希望能對你有所幫助。