Android Kotlin 101: Viết chương trình đầu tiên của bạn
Hành trình vạn dặm từ bước chân đầu tiên. Hãy bắt đầu chương trình Kotlin đầu tiên của bạn từ Blog Post này nhé. Chúc bạn thành công và trở thành một Software Engineer tốt!
Cài đặt IDE
Truy cập đường link: Tải IDE bản Community
Hàm Main – Entry Point
Hãy bắt đầu bằng dòng lệnh và nhấn nút Run ở bên trái hàm main
fun main() {
println("Hello Kotlin!")
}
Kiểu dữ liệu Primary
fun main() {
val integerVariable: Int = 0
println("Integer Variable: $integerVariable")
val floatVariable: Float = 1.111f
println("Float Variable: $floatVariable")
val doubleVariable: Double = 3.14159888
println("Double Variable: $doubleVariable")
val longVariable: Long = 9191488142L
println("Long Variable: $longVariable")
val shortVariable: Short = 32767
println("Short Variable: $shortVariable")
val booleanVariable: Boolean = true
println("Boolean Variable: $booleanVariable")
val stringVariable: String = "Hello, Kotlin!"
println("String Variable: $stringVariable")
val charVariable: Char = 'A'
println("Char Variable: $charVariable")
val byteVariable: Byte = 127
println("Byte Variable: $byteVariable")
}
Kotlin cung cấp đầy đủ các kiểu dữ liệu Primary cần thiết để Lập trình viên có thể viết nên chương trình của họ. Bạn hãy yên tâm về điều này.
Toán tử trên các kiểu dữ liệu cơ sở
fun main() {
val integerVariable: Int = 28283
val integerVariable2: Int = 168
println("Integer Variable: $integerVariable")
println("Integer Variable 2: $integerVariable2")
val addedIntegerVariable: Int = integerVariable + integerVariable2
val subtractedIntegerVariable: Int = integerVariable - integerVariable2
val multipliedIntegerVariable: Int = integerVariable * integerVariable2
val dividedIntegerVariable: Int = integerVariable / integerVariable2
val remainderIntegerVariable: Int = integerVariable % integerVariable2
println("Added: $addedIntegerVariable")
println("Subtracted: $subtractedIntegerVariable")
println("Multiplied: $multipliedIntegerVariable")
println("Divided: $dividedIntegerVariable")
println("Remainder: $remainderIntegerVariable")
} // Similar for other data types
Kotlin cung cấp đầy đủ các toán tử tính toán cho các kiểu dữ liệu cơ sở. Bạn hãy thử với các kiểu dữ liệu khác như Float, Double, String, Byte, Short … để kiểm chứng nhé.
Toán tử trên Bit
Trong thực tế phát triển dự án cả Backend lẫn Desktop, Mobile app bằng ngôn ngữ Kotlin chúng ta rất hiếm khi sử dụng đến công cụ Bitwise (Toán tử trên Bit). Tuy nhiên mình vẫn sẽ cung cấp thông tin để các bạn được nắm và tập luyện khi cần.
fun main() {
val number1 = 12
val number2 = 25
// Bitwise AND
val andResult = number1 and number2
println("Result of Bitwise AND is $andResult")
// Bitwise OR
val orResult = number1 or number2
println("Result of Bitwise OR is $orResult")
// Bitwise XOR
val xorResult = number1 xor number2
println("Result of Bitwise XOR is $xorResult")
// Bitwise Inversion (NOT)
val invResult = number1.inv()
println("Result of Bitwise Inversion (NOT) is $invResult")
// Bitwise Left Shift
val leftShiftResult = number1 shl 2
println("Result of Bitwise Left Shift is $leftShiftResult")
// Bitwise Right Shift
val rightShiftResult = number1 shr 2
println("Result of Bitwise Right Shift is $rightShiftResult")
}
Các toán tử được Kotlin cung cấp và sử dụng một cách dễ dàng.
Khai báo Nullable, NonNullable
NULL
là 1 khái niệm xuất hiện trong hầu hết tất cả các ngôn ngữ lập trình ngày nay. Việc xử lý Null
check là cần thiết và nhất thiết phải có cho tất cả mọi Logic trong dự án.
Kotlin
xử lý vấn đề này bằng cách định nghĩa mỗi biến khi khai báo đều được phải được xác định là 1 Nullable
hoặc NonNullable
. Điều này giúp cho quá trình code trở nên thuận tiện và dễ dàng hơn. Các xử lý Null Check có thể được lược bỏ nếu ta đảm bảo rằng biến đã khai báo là một NonNullable.
Một biến Nullable
khi truy cập sẽ phải sử dụng toán tử ?.
để gọi các properties bên trong chúng. Toán tử này sẽ trả về NULL
nếu biến được gọi là NULL
hoặc property được gọi ra mang giá trị NULL
class MyKotlinObject {
val myKotlinProperty: String = "Hello, Kotlin!"
val myNullKotlinProperty: String? = null
}
fun main() {
val myNonNullKotlinObject = MyKotlinObject()
println("myNonNullKotlinObject.myKotlinProperty: ${myNonNullKotlinObject.myKotlinProperty}")
println("myNonNullKotlinObject.myNullKotlinProperty: ${myNonNullKotlinObject.myNullKotlinProperty}")
val myNullKotlinObject: MyKotlinObject? = null
println("myNullKotlinObject?.myKotlinProperty: ${myNullKotlinObject?.myKotlinProperty}")
println("myNullKotlinObject?.myNullKotlinProperty: ${myNullKotlinObject?.myNullKotlinProperty}")
}
Ví dụ cách sử dụng Null và NonNullable trong Kotlin – Android Mastery by Danh Trần
Khai báo Mutable, Immutable
Kotlin là một ngôn ngữ rất chặt chẽ. Và sự chặt chẽ đó thể hiện ở cách Kotlin
quản lý các biến Mutable
và Immutable
trong chương trình của Lập trình viên.
Immutable
dịch ra tiếng Việt có nghĩa là Bất biến. Có nghĩa là bất kỳ một biến nào trong chương trình được khai báo với kiểu Immutable
đều sẽ không thay đổi giá trị trong suốt vòng đời của chúng.
Để khai báo một biến Immutable
trong Kotlin ta dùng từ khóa val
đứng trước tên biến.
class MyKotlinObject {
val myKotlinProperty: String = "Hello, Kotlin!"
val myNullKotlinProperty: String? = null
}
fun main() {
val myNonNullKotlinObject = MyKotlinObject()
val myNullKotlinObject: MyKotlinObject? = null
myNullKotlinObject = myNonNullKotlinObject // Compilation error
}
Một biến Immutable sẽ chỉ được khai báo giá trị 1 lần duy nhất và không bao giờ được gán lại trong suốt vòng đời của nó.
Ngược lại với Immutable
, Kotlin cung cấp cách khai báo biến Mutable
để biểu thị các biến có thể được gán lại giá trị nhiều lần, trên nhiều Thread, Coroutines khác nhau trong suốt vòng đời của chúng trong chương trình.
Để khai báo một biến Mutable
, ta dùng từ khóa var
đứng trước tên biến.
class MyKotlinObject {
val myKotlinProperty: String = "Hello, Kotlin!"
val myNullKotlinProperty: String? = null
}
fun main() {
var myNonNullKotlinObject: MyKotlinObject = MyKotlinObject()
var myNullKotlinObject: MyKotlinObject? = null
myNullKotlinObject = myNonNullKotlinObject
myNonNullKotlinObject = MyKotlinObject()
}
Khi một biến Mutable được khai báo, chúng sẽ tự do được gán các giá trị mới phù hợp với kiểu dữ liệu đã khai báo trong suốt vòng đời trên chương trình.
class MyKotlinObject {
val myKotlinProperty: String = "Hello, Kotlin!"
val myNullKotlinProperty: String? = null
}
fun main() {
var myNonNullKotlinObject: MyKotlinObject = MyKotlinObject()
var myNullKotlinObject: MyKotlinObject? = null
myNonNullKotlinObject = myNullKotlinObject // Compile Error
}
Chương trình sẽ không thể biên dịch được nếu bạn cố gán một biến Mutable kiểu NonNullable
cho một biến Nullable
Câu lệnh điều kiện, vòng lặp trong Kotlin
Tương tự với các ngôn ngữ lập trình khác. Kotlin cung cấp các công cụ cho lập trình viên dễ dàng xây dựng Logic cho chương trình của họ. Hơn thế nữa trong Kotlin ta có những cú pháp rút gọn tiện dụng hơn rất nhiều.
fun main() {
// readLine() is used to read input from the user
val number: Int = readlnOrNull()?.toIntOrNull() ?: 0
println("Simple if statement")
if (number > 5) {
println("$number is greater than 5")
} else {
println("$number is not greater than 5")
}
println("Advanced if statement")
val checkNumberString = if (number > 5) {
"$number is greater than 5"
} else {
"$number is not greater than 5"
}
// out standing if
println(
if (number > 5) {
"$number is greater than 5"
} else {
"$number is not greater than 5"
}
)
}
Ví dụ cách sử dụng if else
trong Kotlin – Android Mastery
fun main() {
println("Enter the start value:")
val start = readLine()?.toIntOrNull()
println("Enter the end value:")
val end = readLine()?.toIntOrNull()
if (start != null && end != null && start <= end) {
for (i in start..end) {
println("Current number is: $i")
}
} else {
println("Invalid input. Please enter valid start and end values where start is less than or equal to end.")
}
}
Ví dụ cách sử dụng for loop
trong Kotlin – Android Mastery
fun main() {
println("Enter the start value:")
val start = readLine()?.toIntOrNull()
println("Enter the end value:")
val end = readLine()?.toIntOrNull()
if (start != null && end != null && start <= end) {
var i = start
while (i <= end) {
println("Current number is: $i")
i++
}
} else {
println("Invalid input. Please enter valid start and end values where start is less than or equal to end.")
}
}
Ví dụ cách sử dụng while loop trong ngôn ngữ Kotlin – Android Mastery
fun main() {
val obj: Any = "Hello"
// Simple when
when (obj) {
is String -> println("The object is a String. Value: $obj")
is Int -> println("The object is an Integer. Value: $obj")
else -> println("The object is of an unknown type.")
}
// Advanced when
val ret = when (obj) {
is String -> "The object is a String. Value: $obj"
is Int -> "The object is an Integer. Value: $obj"
else -> "The object is of an unknown type."
}
}
Ví dụ cách sử dụng when condition trong ngôn ngữ Kotlin – Android Mastery
Khai báo hàm trong Kotlin
Hàm (function) là một yếu tố không thể thiếu trong Kotlin. Ngôn ngữ lập trình Kotlin cung cấp cho ta rất nhiều cách khai báo và sử dụng hàm (function) một cách linh hoạt.
fun addNumbers(num1: Int, num2: Int): Int {
return num1 + num2
}
fun main() {
val sum = addNumbers(5, 3)
println("The sum is: $sum")
}
Cách khai báo hàm đơn giản nhất trong Kotlin – Android Mastery
fun outerFunction() {
fun innerFunction() {
println("This is the inner function.")
}
println("This is the outer function.")
innerFunction()
}
fun main() {
outerFunction()
}
Cách khai báo inner function trong Kotlin – Android Mastery
val multiply = { num1: Int, num2: Int -> num1 * num2 }
fun main() {
val result = multiply(5, 3)
println("The result is: $result")
}
Cách khai báo hàm là 1 Lambda Expression trong Kotlin (Cách viết ngắn gọn, được nhiều lập trình viên sử dụng) – Android Mastery
Hướng đối tượng trong ngôn ngữ Kotlin
Hướng đối tượng là 1 chủ đề cơ bản trong lập trình. Ở đây ý mình muốn nói Hướng đối tượng là 1 phương pháp lập trình, chúng ta có thể lập trình hướng tối tượng với mọi ngôn ngữ. Tuy nhiên 1 số ngôn ngữ sẽ hỗ trợ việc lập trình hướng đối tượng mạnh hơn 1 số ngôn ngữ khác. Ví dụ ở đây là Kotlin, C++, C#
Kotlin hỗ trợ lập trình Hướng đối tượng với đầy đủ các tính năng: Khai báo Class, Interface, Kế thừa, Đa hình. Ngoài ra Kotlin còn hỗ trợ các tính năng riêng độc đáo của mình như data class
, sealed class
, Object
, Enum class
Hãy tham khảo các đoạn code bên dưới đây
enum class Direction(val direction: String) {
LEFT("LEFT"),
RIGHT("RIGHT"),
FORWARD("FORWARD"),
BACKWARD("BACKWARD"),
STOP("STOP")
}
interface Drivable {
fun drive(direction: Direction)
}
interface Movable {
fun speedUp()
fun speedDown()
}
class Car : Drivable, Movable {
private var speed: Int = 0
companion object {
const val MAX_SPEED = 60
const val MIN_SPEED = 0
}
override fun drive(direction: Direction) {
println("Driving the car turn $direction")
}
override fun speedUp() {
speed++
if (speed > MAX_SPEED) {
speed = MAX_SPEED
}
println("Speeding up the car $speed")
}
override fun speedDown() {
speed--
if (speed < MIN_SPEED) {
speed = MIN_SPEED
}
println("Speeding down the car $speed")
}
}
Ví dụ của OOP trong Kotlin – Android Mastery
data class User(val name: String, val age: Int)
sealed class Expr {
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
}
fun main() {
// Using data class
val user = User("Dan Tech 0xFF", 30)
println(user)
// Using sealed class
val expr1: Expr = Expr.Const(10.0)
val expr2: Expr = Expr.Sum(expr1, Expr.Const(20.0))
val expr3: Expr = Expr.NotANumber
val result = when (expr2) {
is Expr.Const -> "Constant: ${expr2.number}"
is Expr.Sum -> "Sum: ${expr2.e1} + ${expr2.e2}"
Expr.NotANumber -> "Not a number"
}
println(result)
}
Ví dụ cách dùng của data class và sealed class trong Kotlin
Hàm mở rộng (Extension Function) trong Kotlin
Extension function là một tính năng rất hữu ích, mạnh mẽ mà Kotlin cung cấp.
Tính năng Extension function của Kotlin hỗ trợ lập trình viên mở rộng logic của một Class và tái sử dụng chúng hiệu quả mà không cần phải kế thừa class đó.
Điểm giới hạn của Extension function là nó không thể truy cập vào các biến private của Class được. Vì bản chất của Extension function là một static function, được viết gọn lại cho chúng ta dễ sử dụng và Debug.
fun String.countVowels(): Int {
var count = 0
for (char in this) {
if (char in "aeiouAEIOU") {
count++
}
}
return count
}
fun main() {
val word = "Hello"
println("The word '$word' has ${word.countVowels()} vowel(s).")
}
Cách khai báo và sử dụng Extension Function
– Android Mastery
Scope Function
Scope Function là 1 dạng của Extension function, hỗ trợ các phương thức rút gọn khi thao tác lên 1 Kotlin Object.
data class Person(var name: String, var age: Int = 0, var city: String = "")
fun main() {
val person = Person("John")
println("Before update: Hello, $person")
person.apply {
age = 30
city = "New York"
}.apply {
name = "Alice"
} // lưu ý: apply trả về chính receiver object
println("After update: Hello, $person")
}
Cách sử dụng apply
trong Kotlin – Android Mastery
fun main() {
val numbers = mutableListOf("one", "two", "three")
numbers.also {
it.add("four")
println("The list elements before adding new one: $it")
}.add("five")
// Lưu ý: also() nhận vào chính receiver và trả về receiver object
// Lưu ý: add() trả về Unit
println("The list elements after adding new one: $numbers")
}
Cách sử dụng also
trong Kotlin – Android Mastery
fun main() {
val listWithNulls: List<String?> = listOf("Kotlin", null)
for (item in listWithNulls) {
val res = item?.let {
println(it)
"Printed item"
} ?: "Null item"
// Lưu ý: let trả về statement cuối cùng trong block
println("Result: $res")
}
}
Cách sử dụng let trong Kotlin – Android Mastery
Hiểu và dùng lateinit var , val by lazy
lateinit
là từ khóa của Kotlin để thông báo với compiler rằng biến được khai báo với tiền tố lateinit sẽ được khởi tạo giá trị vào 1 thời điểm khác trong chương trình.
Các biến được khởi tạo bởi lateinit
sẽ có dạng mutable
(tức là phải được khai báo với từ khóa var
) và là 1 biến NonNullable
.
Trường hợp Lập trình viên cố tình khai báo biến lateinit
với khai báo Immutable
hoặc với một Nullable
type, trình biên dịch sẽ văng lỗi.
Trường hợp logic truy cập vào 1 biến lateinit
chưa được khởi tạo, chương trình lúc này cũng sẽ văng lỗi. Chính vì điều này chúng ta cần thực sự hiểu luồng chạy của chương trình và sử dụng lateinit
một cách thông minh, hiệu quả.
class User {
lateinit var address: String
fun setAddress(address: String) {
this.address = address
}
fun printAddress() {
if(::address.isInitialized) {
println(address)
} else {
println("Address is not initialized yet.")
}
}
}
fun main() {
val user = User()
user.printAddress() // Prints: Address is not initialized yet.
user.setAddress("1 Le Duan St")
user.printAddress() // Prints: 123 Main St
}
Cách sử dụng lateinit
by lazy
là một từ khóa khác trong Kotlin
. Cụm từ khóa này thông báo cho trình biên dịch hiểu rằng biến được khai báo với by lazy
chưa được khởi tạo giá trị lúc chương trình khởi chạy, thay vào đó giá trị của biến sẽ được khởi tạo ở lần truy cập đầu tiên đến biến đó.
Biến được khai báo bởi by lazy có thể là NonNullable
, hoặc cũng có thể là Nullable
Tuy nhiên, by lazy phải là một Immutable
, điều đó đồng nghĩa suốt vòng đời của biến chỉ mang 1 giá trị duy nhất, chính là giá trị được khởi tạo ở lần truy cập đầu tiên.
class Person {
val name: String by lazy {
println("Initializing name...")
"Dan Tech 0xFF"
}
}
fun main() {
val person = Person()
println(person.name) // This will print "Initializing name..." then "Dan Tech 0xFF"
}
Cách sử dụng val by lazy