12/08/2018, 16:37

Advanced Kotlin Tips for developers

Advanced Kotlin Tips về việc viết code và sử dụng những gì Kotlin cung cấp có rất nhiều lời ích. Có rất nhiều lợi ích của việc sử dụng Kotlin: súc tích, an toàn, và quan trọng là nó interoperable với Java. Kotlin cũng giải quyết rất nhiều vấn đề hạn chế trong Java. Nên bài viết này giới thiệu một ...

Advanced Kotlin Tips về việc viết code và sử dụng những gì Kotlin cung cấp có rất nhiều lời ích. Có rất nhiều lợi ích của việc sử dụng Kotlin: súc tích, an toàn, và quan trọng là nó interoperable với Java. Kotlin cũng giải quyết rất nhiều vấn đề hạn chế trong Java. Nên bài viết này giới thiệu một số Advanced Kotlin Típ giúp mọi người bắt đầu sử dụng và viết code tốt hơn với Kotlin.

1. Singleton

Thực hiện lazy loaded và thread-safe singleton in Kotlin rất đơn giản, không giống như Java là phải dựa vào mô hình khóa kiểm tra tương đối phức tạp double-checked looking pattern.

object Singleton {
    var s: String? = null
}

Singleton trong Kotlin không cần constructor, nhưng method init có thể được sử dụng để khởi tạo nếu cần thiết.

Singleton.s = "test" // class is initialized at this point

2. Utility Functions

Hỗ trợ mở rộng các hàm của Kotlin thông qua các lớp tiện ích Java. Và dễ dàng tiêu thụ hơn trong việc sử dụng mã Java @file:JvmName() để xác định tên của Java class sẽ được tự động sinh ra bởi Kotlin compiler.

// Use this annotation so you can call it from Java code like StringUtil.
@file:JvmName("StringUtil")
fun String.lengthIsEven(): Boolean = length % 2 == 0
val lengthIsEven = "someString".lengthIsEven()

3. Object Initialization

Sử dụng apply cho các câu lệnh khởi tạo để đọc code dễ dàng hơn.

// Don't 
val textView = TextView(this)
textView.visibility = View.VISIBLE
textView.text = "test"
// Do
val textView = TextView(this).apply {
    visibility = View.VISIBLE
    text = "test"
}

4. Một vài Kotlin tips nhỏ cho bạn!

  • let Sử dụng let thay thế cho hàm if(). Kiểm trả đoạn code sau:
val listWithNulls: List<String?> = listOf("A", null)
for (item in listWithNulls) {
    if (item != null) {
        println(item!!)
    }
}

Với sử dụng let thay thế cho if()

val listWithNulls: List<String?> = listOf("A", null)
for (item in listWithNulls) {
    item?.let { println(it) } // prints A and ignores null
}
  • When() When() thay thế cho switch operator của Java và nó có clean hơn là sử dụng if conditions
// Java
public Product parseResponse(Response response) {
   if (response == null) {
       throw new HTTPException("Something bad happened");
   }
   int code = response.code();
   if (code == 200 || code == 201) {
       return parse(response.body());
   }
   if (code >= 400 && code <= 499) {
       throw new HTTPException("Invalid request");
   }
   if (code >= 500 && code <= 599) {
       throw new HTTPException("Server error");
   }
   throw new HTTPException("Error! Code " + code);
}

Sử dụng when

// Kotlin
fun parseResponse(response: Response?) = when (response?.code()) {
   null -> throw HTTPException("Something bad happened")
   200, 201 -> parse(response.body())
   in 400..499 -> throw HTTPException("Invalid request")
   in 500..599 -> throw HTTPException("Server error")
   else -> throw HTTPException("Error! Code ${response.code()}")
}

5. Read-only List, Map...

Kotlin phân biệt giữa Mutable và Immutable collections(list, map, set...). Kiểm soát chính xác collections rất hữu ích để loại bỏ lỗi và thiết kế các API tốt. Library của Kotlin chứa các hàm tiện ích cho cả mutable và immutable collections. Ví dụ listOf() và mutableListOf()

val list = listOf(“a”, “b”, “c”)
val map = mapOf("a" to 1, "b" to 2, "c" to 3)

6. Lazy Property

lazy is good, nó giúp tiết kiệm bộ nhớ và tiết kiệm chu kỳ CPU nếu khởi tạo của nó expensive.

val str: String by lazy {
     // Compute the string
}

7. Local functions

Local functions are good cho việc tái sử dụng, cẩn thận sử dụng để tránh lạm dụng.

fun foo(a: Int) {
    fun local(b: Int) {
        return a + b
    }
    return local(1)
}

8. Infix functions

Infix functions are good, nó giúp cho chúng ta dễ dàng đọc code, bởi vì nó cho phép nhập một số thứ như "test" foo "x" ví dụ:

infix fun String.foo(s: String) {
    ...
}
// Call extension function.
"test".foo("x")
// Or call extension function using infix notation.
"test" foo "x"

Infix function chỉ sử dụng cho function có 1 parameter

9. Inline functions

Lambda expression trong Kotlin được dịch sang lớp ẩn danh trong Java 6 hoặc 7. Lambda tác động tăng hiệu suất. inline functions được sử dụng để thay thế các phương thức khác và thêm vào đó call stack vì vậy nó có ý nghĩa là thêm đoạn code trong inline function cho chỗ gọi chúng

inline fun callBlock(block: () -> Unit) {
    println("Before calling block")
    block()
    println("After calling block")
}

Khi chúng ta gọi phương thức **callBlock** nó sẽ được dịch như dưới đây:

callBlock { println("The block operation") }
// Rough java bytecode
String var1 = "Before calling block";
System.out.println(var1)
String var2 = "The block operation";
System.out.println(var2);
var1 = "After calling block";
System.out.println(var1);

Với functions không phải là inline functions

callBlock { println("The block operation") }
// Rough java bytecode
callBlock((Functinos0)null.INSTANCE);

Chú ý: không nên sử dụng inline function khi mà đoạn code trong inline functions quá lớn

10. Tail recursion

Khi sử dụng tailrec chúng tôi cho phép compiler biết rằng nó có thể thay thế các method với for loop hoặc goto stament

tailrec fun findFixPoint(x: Double = 1.0): Double         
       = if (x == Math.cos(x)) x else findFixPoint(Math.cos(x))
       ```
0