A modern programming language that makes developers happier!
Kotlin’s modern language features allow you to focus on expressing your ideas and write less boilerplate code.
With @Nullable and @NonNull included in its type system, Kotlin helps you avoid NullPointerExceptions. Android apps that use Kotlin are 20% less likely to crash.
Kotlin is 100% interoperable with the Java programming language, so you can have as little or as much of Kotlin in your project as you want.
Kotlin coroutines streamline asynchronous programming, making common tasks like network calls and database updates simple and performant.
The below will show you the best practice in Kotlin.
1. Creating DTOs (POJOs/POCOs)
data class User(val name: String, val email: String)
Data class provides a class with the following functionality:
- getters (and setters in case of vars) for all properties
equals()
hashCode()
toString()
copy()
Requirements:
- The primary constructor needs to have at least one parameter;
- All primary constructor parameters need to be marked as
val
orvar
; - Data classes cannot be abstract, open, sealed or inner;
Impossible Inheritance is the worst restriction of the data class.
For example, a class Manager can not inherit the User class.
// Invalid code
class Manager(...): User(...)
2. Default values for function parameters
fun foo(a: Int = 0, b: String = "") { ... }
Sometimes, the default values might make some unexpected results. So developers have to be careful when making default values.
3. Lazy property, Lateinit property
Lazy: This is a delegated Properties in Kotlin. The first call to get()
executes the lambda passed to lazy()
and remembers the result, subsequent calls to get()
simply return the remembered result.
val currentUser: User by lazy {
// compute the current user
}
Late-Initialized: Normally, properties declared as having a non-null type must be initialized in the constructor. However, fairly often this is not convenient.
To handle this case, you can mark the property with the lateinit
modifier:
lateinit var user: User
Accessing a lateinit
property, before it has been initialized, throws a special Exception that clearly identifies the property being accessed and the fact that it hasn't been initialized.
4. Extension Functions, Property
Extension function is a useful feature in Kotlin. Instead of writing a lot of Helpers, Converters… class, now you can write a simple extension function to execute a behavior related to the class.
fun User.isValidToJoinMeeting(): Boolean {...}
fun User.Companion.printMaxUserSize() {...}val User.isMale: Boolean = {...}
val User.Companion.maxUser: Int = {...}
5. Singleton
object DataProvider {}
6. Single-expression functions
fun theAnswer() = 42// Same to
fun theAnswer(): Int {
return 42
}
7. Generic function
inline fun <reified T: Any> Gson.fromJson(json: JsonElement): T = this.fromJson(json, T::class.java)
8. Swapping two variables
var a = 1
var b = 2
a = b.also { b = a }
9. TODO(): Marking code as incomplete
fun calcTaxes(): BigDecimal = TODO("Waiting for feedback from accounting")
10. Label
loop@ for (i in 1..100) {
for (j in 1..100) {
if (...) break@loop
}
}// Print 1245 done with explicit label
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@{
if (it == 3) return@lit
print(it)
}
print(" done with explicit label")
}
11. Functional (SAM) interfaces
fun interface IntPredicate {
fun accept(i: Int): Boolean
}// Creating an instance using lambda
val isEven = IntPredicate { it % 2 == 0 }
12. Sealed Classes
Sealed classes are used for representing restricted class hierarchies, when a value can have one of the types from a limited set, but cannot have any other type. They are, in a sense, an extension of enum classes: the set of values for an enum type is also restricted, but each enum constant exists only as a single instance, whereas a subclass of a sealed class can have multiple instances which can contain state.
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()fun eval(expr: Expr): Double = when(expr) {
is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
// the `else` clause is not required because we've covered all the cases
}
13. Type aliases
typealias NodeSet = Set<Network.Node>typealias FileTable<K> = MutableMap<K, MutableList<File>>typealias MyHandler = (Int, String, Any) -> Unittypealias Predicate<T> = (T) -> Boolean
14. Delegate Observable
class User {
var name: String by Delegates.observable("<no name>") {
prop, old, new ->
println("$old -> $new")
}
}
Hope you have a better experience with Kotlin tip tricks.