Kotlin/程式撰寫慣例

程式撰寫慣例

編輯

套用規範建議

編輯

To configure the IntelliJ formatter according to this style guide, please install Kotlin plugin version 1.2.20 or newer, go to Settings | Editor | Code Style | Kotlin, click Set from… link in the upper right corner, and select Predefined style | Kotlin style guide from the menu.

To verify that your code is formatted according to the style guide, go to the inspection settings and enable the Kotlin | Style issues | File is not formatted according to project settings inspection. Additional inspections that verify other issues described in the style guide (such as naming conventions) are enabled by default.

程式碼架構

編輯

命名規則

編輯

函式名稱

編輯

函式名稱,參數以及本地變數的命名,都是小寫開頭的駝峰格式,不包含底線:

fun processDeclarations() { /*...*/ }
var declarationCount = 1

例外情況:建立某介面的物件所使用的工廠方法,可以直接用該介面命名,因此是大寫開頭:

interface Foo { /*...*/ }

class FooImpl : Foo { /*...*/ }

fun Foo(): Foo { return FooImpl() }

測試函式名稱

編輯

如果是在測試程式碼裏面(也僅有在測試程式程式碼內允許),可以使用重音符「`」括弧起來,內含空白的一段文字作為函式名稱。這類函式目前在 Android 實際環境運作是不支援的。

測試程式碼內,也允許在函式命名裏面使用底線。

class MyTestCase {
     @Test fun `ensure everything works`() { /*...*/ }
     
     @Test fun ensureEverythingWorks_onAndroid() { /*...*/ }
}

屬性名稱

編輯

常量名稱(標有 const 的屬性,或者保存不可變數據的沒有自定義 get 函數的頂層/對象 val 屬性)應該使用大寫、以底線分隔的風格命名:

const val MAX_COUNT = 8
val USER_NAME_FIELD = "UserName"

帶有行為的物件,或者可變數據的頂層/對象屬性的名稱,應該使用小駝峰風格命名:

val mutableCollection: MutableSet<String> = HashSet()

保存單例對象引用的屬性的名稱,可以使用與 object 定義相同的風格命名:

val PersonComparator: Comparator<Person> = /*...*/

對於枚舉常數的命名,可以使用大寫以底線分隔的名稱 (enum class Color { RED, GREEN })也可使用大駝峰命名,具體命名風格取決於用途。

為備存用屬性命名

編輯

如果一個類別有兩個概念相同的屬性,一個是對外的部分,另一個是內部實作細節,那麼使用下劃線作為私有屬性名稱的前綴:

class C {
    private val _elementList = mutableListOf<Element>()

    val elementList: List<Element>
         get() = _elementList
}

選好的名字

編輯

類別的名字通常會是某個名詞或名詞片語,解釋這個類別在做什麼,比方說:ListPersonReader

函式的名稱通常是動詞或者動詞片語,解釋這個函式的行為,比方說:closereadPersons

函式名稱應該要看得出來其行為是改變輸入的參數,還是回傳一個新的物件。比方說:sort 通常是將輸入的集合進行排序,不會回傳新的集合;sorted 則是回傳一個以排序好的集合,不會更動輸入的集合。

命名要能夠看得出用意,所以命名內盡量避免意義不清晰的單字(比方說 Manager,Wrapper 之類)

如果在宣告名稱中使用縮寫,該縮寫只有兩個字母(比方說 I/O)的話,兩個字母都要大寫(IOStream)。如果該縮寫多於兩個字母,那麼只有第一個字母要大寫(XmlFormatter,HttpInputStream)

格式

編輯

用四個空白縮排,不要用 Tab

左大括號前面加上一個空白,並且放在結構一開始這行的最尾端。

右大括號則是獨立一行,並對其結構宣告的開頭。

if (elements != null) {
    for (element in elements) {
        // ...
    }
}

(註記:Kotlin 裏,分號是非必須的,所以換行非常重要。編譯器會假設你是用以上風格的括號方式,如果使用不同風格,可能會導致意外的編譯結果)

橫向空白

編輯

除了「範圍」運算子不需要之外(0..1),二元運算子前後各需要一個空白(比方說: a + b)。

一元運算子前後不可加上空白(比方說:a++)

控制流關鍵字(if、when、for 和 while)和對應的小括號之間要加上一個空白

Do not put a space before an opening parenthesis in a primary constructor declaration, method declaration or method call.

class A(val x: Int)

fun foo(x: Int) { ... }

fun bar() {
    foo(1)
}


Never put a space after (, [, or before ], ).

Never put a space around . or ?.: foo.bar().filter { it > 2 }.joinToString(), foo?.bar()

單行註解的 // 後面要加上一個空白,比方說:// 這是單行註解

Do not put spaces around angle brackets used to specify type parameters: class Map<K, V> { ... }

Do not put spaces around ::: Foo::class, String::length

Do not put a space before ? used to mark a nullable type: String?

As a general rule, avoid horizontal alignment of any kind. Renaming an identifier to a name with a different length should not affect the formatting of either the declaration or any of the usages.

冒號

編輯

類別宣告格式

編輯

修飾宣告

編輯

標註格式

編輯

檔案標註

編輯

函式格式

編輯

Expression body formatting

編輯

Property formatting

編輯

Formatting control flow statements

編輯

Method call formatting

編輯

Chained call wrapping

編輯

Lambda 格式

編輯

文件註解

編輯

避免多餘結構

編輯

如果函式回傳 Unit 那麼可以省略

fun foo() { // ": Unit" 被省略了

}

分號

編輯

盡量避免分號

字串樣板

編輯

如果樣板內只有單純變數名稱,避免用大括號包起來。只有在樣板包含比較長的表達式時才需要用大括號處理

println("$name has ${children.size} children")

慣用語言功能

編輯

Immutability

編輯

Default parameter values

編輯

Type aliases

編輯

Lambda parameters

編輯

Returns in a lambda

編輯

Named arguments

編輯

Using conditional statements

編輯

if versus when

編輯

Using nullable Boolean values in conditions

編輯

Using loops

編輯

Loops on ranges

編輯

Using strings

編輯

Functions vs Properties

編輯

Using extension functions

編輯

Using infix functions

編輯

Factory functions

編輯

Platform types

編輯

Using scope functions

編輯

library 的撰寫慣例

編輯

When writing libraries, it's recommended to follow an additional set of rules to ensure API stability:

  • Always explicitly specify member visibility (to avoid accidentally exposing declarations as public API)
  • Always explicitly specify function return types and property types (to avoid accidentally changing the return type when the implementation changes)
  • Provide KDoc comments for all public members, with the exception of overrides that do not require any new documentation (to support generating documentation for the library)

參考資料

編輯