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)

参考资料

编辑