欢迎访问我的个人网站:https://coderyuan.com
1 介绍
本规范参考Android官方Kotlin编码规范,旨在为Kotlin开发人员提供编码风格上的指导,仅供参考,如果翻译上的失误或建议,欢迎反馈!
2 源文件规范
2.1 文件编码
- 所有源文件必须使用UTF-8进行编码
2.2 文件命名
-
所有源文件必须使用
.kt
作为扩展名 -
如一个源码文件仅包含一个顶级类,则该文件应当以这个定级类的类名作为文件名,如包含多个顶级定义,请选择一个能够描述该文件内容的名字作为文件名
2.3 特殊字符
2.3.1 空格
-
除了换行符之外,ASCII空格(0x20)是唯一合法的空格字符
- 所有在源代码中(包括字符、字符串以及注释中)出现的其他空格字符都需要转义
- Tab不可以用于缩进
2.3.2 特殊转义字符
- 任何含有特殊意义的转义字符,如:
\b
、\n
、\r
、\t
、\'
、\''
、\\
、\$
等,不可以使用Unicode进行转义
2.3.3 非ASCII字符
-
对于其他的非ASCII字符,建议使用其实际字符,如:
∞
,应尽最大可能保证代码的可读性 -
任何时候,包括所有代码、注释、文档中,都不推荐使用Unicode编码进行转义
示例 | 说明 |
---|---|
val unitAbbrev = "μs" |
最佳写法,不使用注释也可以看懂 |
val unitAbbrev = "\u03bcs" // μs |
不推荐的写法,使用转义字符没有任何意义 |
val unitAbbrev = "\u03bcs" |
禁止的写法,读者完全无法理解意义 |
return "\ufeff" + content // byte order mark |
不错的写法,可打印字符使用转义字符,并添加了必要的注释 |
2.3.4 文件结构
-
一个以
.kt
结尾的文件必须按照以下顺序填充并组织内容:- 版权(Copyright)及许可证(License)头部声明(可选)
- 文件级的注解
- package声明语句
- import语句
- 顶级定义
以上各项内容间,使用一个空行分隔
2.3.4.1 版权/许可证
-
建议使用如下格式声明版权信息,并添加作者信息:
/* * Copyright 2019 coderyuan.com. All Rights Reserved. * * coderyuan created at 2019/9/20 19:08 */
2.3.4.2 文件级注解
-
文件级注释请参考Kotlin官方文档(https://kotlinlang.org/docs/reference/annotations.html#annotation-use-site-targets),根据相应的类型来合理使用注解,但必须在版权/许可证之后,package声明语句之前
@file:JvmName("Foo") package com.coderyuan.demo
2.3.4.3 Package声明语句
- package(包)声明语句不受列数限制,并且永远不会换行
2.3.4.4 Import语句
-
import语句可以用于导入类、方法、属性,它们集合在一个列表之内,应按包名的ASCII顺序排序
-
import语句和package语句一样,不受列数限制,不进行折行
-
禁止使用通配符
-
未使用的import语句,应及时删除,但在使用Kotlin Android Extensions时,请注意不要删除IDE误报的import语句
2.3.4.5 顶级(Top-Level)定义
-
一个
.kt
文件中可以定义一个或多个顶级类型、方法、属性、类别名 -
一个源文件中的内容必须针对同一个主题,不相干的声明必须拆分到其各自所属的文件中去,使一个文件尽量变小
-
对文件内容的数量和顺序没有严格的规定,但应最大程度保证文件的可阅读性
-
每个类都应该以业务逻辑顺序排列,而不应仅仅按时间顺序添加在最末尾
2.3.4.6 类成员顺序
- 成员顺序要求,与顶级定义中的顺序要求保持一致
3 格式
3.1 花括号
3.1.1 基本使用
-
单行的
when
语句分支、单行的if
语句(用于代替三目运算符)不强制要求添加花括号if (string.isEmpty()) return val value = if (a == b) 0 else 1 when (value) { 0 -> return // … }
-
除以上情况外,任何使用
if
、when
、for
、do
、while
语句时,对于其有效作用域,都必须使用花括号,即使其中只有一行代码// Good val myValue = if (condition) { 0 } else { 1 } // Bad val myValue = if (condition) 0 else 1
3.1.2 非空代码块情况
-
在非空代码块中使用花括号时要遵循K&R风格(Kernighan and Ritchie Style):
- 左花括号(
{
)前不能换行,在其后换行 - 在右花括号(
}
)前要有换行 - 如果右花括号是一句语句,或者一个方法、构造函数、非匿名类的结尾,其后需要换行,其他情况不进行换行,如右花括号后是
else
或者逗号的情况
return Runnable { while (condition()) { foo() } } return object : MyClass() { override fun foo() { if (condition()) { try { something() } catch (e: ProblemException) { recover() } } else if (otherCondition()) { somethingElse() } else { lastThing() } } }
- 左花括号(
3.1.2 空代码块情况
-
空的代码块、构造方法也必须遵循K&R风格
try { doSomething() } catch (e: Exception) { } // WRONG!
try { doSomething() } catch (e: Exception) { } // Okay
3.2 缩进
- 每次开始书写一个新的代码块时,使用4个空格进行缩进,在代码块结束时,恢复之前的缩进级别,该级别适用于整个块中的代码和注释
3.3 每行一句代码
- 每句语句后都必须使用一个换行,不使用分号
3.4 代码折行
-
建议代码每行不超过120字符,如过长须折行书写或进行缩减
-
例外情况:
- 120字符无法满足的情况,如:注释中一个很长的URL
package
及import
语句- 注释中需要复制粘贴的shell脚本
3.4.1 折行规则
-
折行规则的主旨:在更高阶的语法处进行折行,最终目的是为了保证代码可读性:
- 非赋值运算符,在运算符前进行折行,同样适用于
.
和::
两种符号 - 赋值运算符,在运算符后进行折行
- 方法或构造函数后的左括号,应保持在同一行
,
(逗号)与其之前的内容保持在一行- Lambda箭头运算符
->
与其之前的参数列表保持在一行
- 非赋值运算符,在运算符前进行折行,同样适用于
3.4.2 连续缩进
-
换行时,第一行(每个连续行)之后的每一行至少缩进8个空格
-
如有多个连续行时,缩进可以超过8个,当且仅当它们以语法并行元素开头时,才使用同样的缩进级别
3.4.3 方法折行
-
当一个方法的签名无法写在一行时,请按参数定义进行折行:
- 每行定义一个参数,同时使用比方法多4个字符的空格进行缩进
- 右括号和返回类型的定义单独放在一行内,这一行不需要缩进
fun <T> Iterable<T>.joinToString( separator: CharSequence = ", ", pre