Kotlin - Need to know - part 1
Bài đăng này đã không được cập nhật trong 4 năm
Seri bài viết tổng hợp những kiến thức cơ bản trong Kotlin cần nhớ.
1. In Kotlin, everything is an object
In Kotlin, everything is an object in the sense that we can call member functions and properties on any variable. Some of the types can have a special internal representation - for example, numbers, characters and booleans can be represented as primitive values at runtime - but to the user they look like ordinary classes.
Giống những ngôn ngữ khác, Kotlin
có định nghĩa sẵn những type
như Int
, Double
, Boolean
, Char
... Tuy nhiên, trong Kotlin
, mọi thứ đều là đối tượng theo nghĩa mọi thứ đều hoạt động như một đối tượng, chúng ta có thể gọi các member functions
và member properties
trên bất cứ một biến (variable
) nào.
Kotlin có thể diễn tả một số kiểu cơ bản như numbers, characters và booleans là các giá trị nguyên thủy (primitive value) ở thời điểm runtime để tăng performance, nhưng với end user tất cả chúng đều là đối tượng.
Trong hầu hết các trường hợp như khai báo, Kotlin Basic Types
sẽ compiled sang Java Primitive Types
để tăng performance, ngoại trừ một vài trường hợp đặc biệt:
Khai báo Basic Type ở dạng Nullable Object:
var a : Long? = null
a = 100L
val b = 200L
// the compiled code is below
Long a = (Long)null;
a = 100L;
long b = 200L;
Vì lý do trong Java platform, numbers được lưu vật lý dưới dạng JVM primitive type, trừ trường hợp chúng ta cần một nullable number reference (vd Long?
...) hoặc generics, trong các trường hợp còn lại numbers là Boxed
.
// Note === is Equality operators / Referential equality, it will only be true
// if both the objects or variables pointing to the same object.
val a: Long = 10000L
println(a === a) // Prints 'true'
val boxedA: Long? = a
val anotherBoxedA: Long? = a
println(boxedA === anotherBoxedA) // !!!Prints 'false'!!!
// Hypothetical code, does not actually compile:
val a: Int? = 1 // A boxed Int (java.lang.Integer)
val b: Long? = a // implicit conversion yields a boxed Long (java.lang.Long)
print(b == a) // Surprise! This prints "false" as Long's equals() checks whether the other is Long as well
Khai báo kiểu Array Object:
val a = arrayOf(1, 2, 3)
val b = intArrayOf(1, 2, 3)
// The compiled code is below
Integer[] var10000 = new Integer[]{1, 2, 3};
int[] var2 = new int[]{1, 2, 3};
Trong Kotlin, Array
là invariant
(Một khái niệm trong Generics, sẽ nói trong bài viết khác) nghĩa là ko cho phép gán một Array<String>
cho một Array<Any>
.
Kiểu Primitive type arrays
(ByteArray, ShortArray, IntArray
...) cho phép biểu diễn một mảng nguyên thủy mà không cần boxing overhead
, các lớp này không có quan hệ kế thừa đối với lớp Array
, nhưng có chung tập các phương thức và thuộc tính.
=> Như vậy, Kotlin không có khái niệm về kiểu nguyên thủy Primitive Types
mà chỉ có Basic Types
2. Null-Safety and Platform Types
Bất cứ một tham chiếu nào từ Java đều có thể là null
, điều này làm cho các yêu cầu nghiêm ngặc về null-safety
trong Kotlin trở nên không thực tế đối với các đối tượng đến từ Java (điều này thường gặp trong android khi Android SDK đa số đang là Java code).
Types của các khai báo java được xử lý đặc biệt trong Kotlin và được gọi là những Platform Types
. Null-check
được nới lỏng cho các type này, do đó đảm bảo an toàn cho chúng giống như trong Java.
val list = ArrayList<String>() // non-null (constructor result)
list.add("Item")
val size = list.size // non-null (primitive int)
val item = list[0] // platform type inferred (ordinary Java object)
//
item.substring(1) // allowed, may throw an exception if item == null
trong ví dụ trên đối tượng item
(là một Java ArrayList item) được xem như là Platform Type
, Kotlin sẽ không báo nullability error
lúc compile time, nhưng lời gọi item.substring(1)
trên có thể lỗi lúc runtime
Trong android, một ví dụ thường thấy là lúc findViewById
val textView = findViewById<TextView>(R.id.textView) // Platform type: TextView!
textView?.text = "Maybe I'm null"
textView.text = "Maybe I'm not null"
Platform types là non-denotable
, nghĩa là chúng ta không thể viết chúng xuống trực tiếp bằng ngôn ngữ, trong ví dụ trên không thể khai báo kiểu TextView!
. Khi Platform type được gán cho một biến Kotlin, chúng ta có thể dựa trên Type inference
(kiểu suy luận) hoặc có thể chọn type mà chúng ta expect (cả nullable và non-null đều được cho phép).
val nullable: String? = item // allowed, always works
val notNull: String = item // allowed, may fail at runtime
Notation for Platform Types
Như nói ở trên, Platform Type không thể được mentioned explicity
(đề cập rõ ràng) trong chương trình, nên không có một cú pháp nào cho chúng trong ngôn ngữ. Tuy nhiên, trình biên dịch và IDE đôi khi cần hiển thị chúng (ví dụ trong error message, parameter...), vì vậy, Kotlin có 1 vài kí hiệu ghi nhớ cho Platform Type:
T!
nghĩa làT?
hoặcT
(Mutable)Collection<T>!
nghĩa là Java collection của T có thể mutable hoặc immutable, có thể nullable hoặc không.Array<out T>!
nghĩa là Java array of T (hoặc một subtype of T) có thể nullable hoặc không
3. Kotlin Expression and Statement
Đây là 2 khái niệm quan trọng thường bị hiểu nhầm.
Expression
An expression in a programming language is a combination of one or more explicit values, constants, variables, operators and functions that the programming language interprets and computes to produce another value. (Theo wikipedia)
Một expression trong ngôn ngữ lập trình là sự kết hợp của một hay nhiều explicit values, constants, variables, operators and functions
mà ngôn ngữ diễn giải và tính toán để tạo ra một giá trị khác.
Vì thế, đơn giản 1+1
là một expression, sumOf(1,2,3)
cũng vậy. Chú ý rằng một expression có thể chứa expression khác, ví dụ expression sumOf(1, 2*3)
chứa expression 2*3
.
An expression is every part of code that returns value.
Tức là một expression là tất cả những phần của code có trả về giá trị. Do đó, có thể dựa theo kinh nghiệm rằng những phần code bạn có thể gán giá trị của nó cho một biến hoặc truyền nó như là một argument của method thì đó là một expression.
Vì mọi function trong Kotlin đều trả về ít nhất là Unit
(chú ý rằng Unit
có thể obmitted
trong function), vì vậy mỗi function invocation / function call
là một expression.
fun sayHello() {
// function block
}
println(sayHello()) // print
// sayHello() is an Expression
// println(sayHello()) is an Expression that contains another Expression
// and it is also a Statement because it is a standalone Expression
Trong java
, if
luôn là statement
, nhưng trong kotlin
, if
hay when
hoặc try
được phép return giá trị nên bạn có thể sử dụng chúng như là một expression hoặc một statement.
// Traditional usage
var max = a
if (a < b) max = b
// use as statement with else
var max: Int
if (a > b) {
max = a
} else {
max = b
}
// use as expression
val max = if (a > b) a else b
// if branches can be blocks, and the last expression is the value of a block:
val max = if (a > b) {
print("Choose a")
a // the value of this block
} else { // in this case the expression is required to have an else branch
print("Choose b")
b // the value of this block
}
// When
val color = when {
relax -> GREEN
studyTime -> YELLOW
else -> BLUE
}
// Try
val response = try {
gson.fromJson(json)
} catch (e: Throwable) {
null
}
Trong Kotlin, return, break, continue
là các structural jump expressions
, type của những expression này là Nothing
type (sẽ trình bày trong bài viết khác). Trong java, chúng đều là branching statement
.
Statement
In computer programming, a statement is a syntactic unit of an imperative programming language that expresses some action to be carried out. (Theo wikipedia)
Trong lập trình, một statement
là một đơn vị cú pháp (syntactic unit
) của một ngôn ngữ lập trình mệnh lệnh, nó thể hiện một số hành động sẽ được thực hiện.
Trong Kotlin, một statement có thể là:
- Variable declaration, ex:
val a = 10
- Variable or property assignment, ex
a = 20
- Local class declaration, ex:
class A {}
Expression độc lập (Standalone expression
) cũng là một statement
Vd: updateUser(user)
.
Đến đây bạn có thể tự giải đáp một vài điểm khác giữa Java và Kotlin
// Java
int a, b;
b = 2; // Java statement in this case (it is called assignment statement)
a = b = 2; // work only in Java because b = 2 in this case it is called assignment expression
// However, in Kotlin, b = 2 is already a statement.
a = b == 2 ? 2 : 1; // Java allowed ternary operator which not in Kotlin because Kotlin allow if return value
a = if (b == 2) 2 else 1 // same as above Java statement
// and more...
TO BE CONTINUED
References:
All rights reserved