Kotlin is a statically-typed programming language that runs on the JVM and can also be compiled to JavaScript. It provides modern language features and has been designed to be completely interoperable with Java code.
All Kotlin code is expected to adhere to our Java Style Guidelines where applicable.
We follow standard Kotlin coding conventions with the addition of a few rules:
- Type names are written as
UpperCamelCase
- Method and properties are written as
lowerCamelCase
- Constants and immutable properties are written as
ALL_CAPS_WITH_UNDERSCORES
For example:
class MyClass {
private val field = 0
fun getValue() = field
companion object {
const val LOG_TAG = "MyClass"
}
}
For classes that extend an Android component, the name of the class should end with the name of the component; for example: SignInActivity
, SignInFragment
, ImageUploaderService
, ChangePasswordDialog
.
There should be a space before a colon when it separates type and supertype, but not when the colon separates instance and type:
interface Foo<out T : Any> : Bar {
fun foo(a: Int): T
}
Types can be inferred by variable assignment in Kotlin and should be omitted unless necessary:
val bar = 10 // ": Int" is inferred
If a function returns Unit, the return type should be omitted:
fun foo() { // ": Unit" is omitted here
// ...
}
Braces do not go on their own line; they go on the same line as the code before them:
class MyClass {
fun func(): Int {
if (something) {
// ...
} else if (somethingElse) {
// ...
} else {
// ...
}
}
}
We require the body of a statement to start on a new line with the following exceptions:
- The body is a lambda parameter with a single line:
observable?.let { subscribe(it) }
- The body is a single method call:
if (condition) doSomething()
- The body only contains the body of a keyword, then that keyword can be lifted:
if (condition) with(something) {
setupSomethingAdapter(this)
setupSomethingViews(this)
}
// ...
if (condition) try {
doSomething()
} finally {
logSomething()
}
- Ternary operations in Kotlin are represented as if/else statements and are allowed to be a single line:
val result = if (condition) 1 else 2
Companion objects should always be declared at the bottom of the class. Fields within a companion object should follow our naming conventions:
class MainActivity : Activity() {
// ...
companion object {
const val EXTRA_TITLE = "extra_title"
const val EXTRA_URL = "extra_url"
}
}
Objects and properties should not be nullable whenever possible. !!
should rarely be used and ?
should be used sparingly. Limiting the number of nullable objects and properties will reduce the need for null checks and will provide for more stable code.
Always prefer string interpolation over concatenation:
val name = "${user.first} ${user.last}"
Case branches in when() statements should be a single line:
return when (field) {
is String -> field
is Int -> field.toString()
else -> ""
}
Global extension functions should be used moderately and only when the extended class source code is not available or modifiable.