Chương trình đào tạo về Kotlin dành cho lập trình viên 6: Thao tác chức năng

Lớp học lập trình này nằm trong khoá học Chương trình đào tạo về Kotlin dành cho lập trình viên. Bạn sẽ nhận được nhiều giá trị nhất qua khoá học này nếu thực hiện các lớp học lập trình theo trình tự. Tuỳ thuộc vào kiến thức của mình, bạn có thể lướt qua một số phần. Khoá học này hướng tới những lập trình viên biết một ngôn ngữ hướng đối tượng và muốn học Kotlin.

Giới thiệu

Đây là lớp học lập trình cuối cùng trong Chương trình đào tạo về Kotlin. Trong lớp học lập trình này, bạn sẽ tìm hiểu về chú giải và điểm ngắt được gắn nhãn. Bạn sẽ ôn lại về lambda và hàm bậc cao, đây là những phần quan trọng của Kotlin. Bạn cũng sẽ tìm hiểu thêm về các hàm nội tuyến và giao diện Phương thức trừu tượng đơn (SAM). Cuối cùng, bạn sẽ tìm hiểu thêm về Thư viện chuẩn Kotlin.

Thay vì tạo một ứng dụng mẫu duy nhất, các bài học trong khoá học này được thiết kế để giúp bạn nâng cao kiến thức, nhưng các bài học này có tính độc lập tương đối với nhau để bạn có thể lướt qua những phần mà bạn đã quen thuộc. Để liên kết các ví dụ này với nhau, nhiều ví dụ sử dụng chủ đề hồ cá. Nếu bạn muốn xem toàn bộ câu chuyện về bể cá, hãy tham khảo khoá học Kotlin Bootcamp dành cho lập trình viên của Udacity.

Kiến thức bạn cần có

  • Cú pháp của các hàm, lớp và phương thức Kotlin
  • Cách tạo một lớp mới trong IntelliJ IDEA và chạy một chương trình
  • Kiến thức cơ bản về hàm lambda và các hàm bậc cao

Kiến thức bạn sẽ học được

  • Những nội dung cơ bản về chú thích
  • Cách sử dụng điểm ngắt được gắn nhãn
  • Tìm hiểu thêm về các hàm bậc cao
  • Giới thiệu về giao diện Phương thức trừu tượng đơn (SAM)
  • Giới thiệu về Thư viện chuẩn Kotlin

Bạn sẽ thực hiện

  • Tạo một chú thích đơn giản.
  • Sử dụng điểm ngắt có nhãn.
  • Xem lại các hàm lambda trong Kotlin.
  • Sử dụng và tạo các hàm bậc cao hơn.
  • Gọi một số giao diện Phương thức trừu tượng đơn.
  • Sử dụng một số hàm trong Thư viện chuẩn Kotlin.

Chú giải là một cách để đính kèm siêu dữ liệu vào mã và không phải là một thứ dành riêng cho Kotlin. Trình biên dịch sẽ đọc các chú thích này và dùng chúng để tạo mã hoặc logic. Nhiều khung hình, chẳng hạn như KtorKotlinx, cũng như Room, sử dụng chú thích để định cấu hình cách chúng chạy và tương tác với mã của bạn. Bạn khó có thể gặp phải chú thích cho đến khi bắt đầu sử dụng các khung, nhưng bạn nên biết cách đọc chú thích.

Ngoài ra, còn có các chú thích có trong thư viện chuẩn của Kotlin giúp kiểm soát cách biên dịch mã. Chúng thực sự hữu ích nếu bạn xuất Kotlin sang mã Java, nhưng nếu không thì bạn không cần chúng thường xuyên.

Chú thích xuất hiện ngay trước đối tượng được chú thích và hầu hết mọi thứ đều có thể được chú thích – lớp, hàm, phương thức và thậm chí cả cấu trúc điều khiển. Một số chú giải có thể nhận đối số.

Dưới đây là ví dụ về một số chú thích.

@file:JvmName("InteropFish")
class InteropFish {
   companion object {
       @JvmStatic fun interop()
   }
}

Điều này có nghĩa là tên được xuất của tệp này là InteropFish có chú thích JvmName; chú thích JvmName đang lấy một đối số là "InteropFish". Trong đối tượng companion, @JvmStatic yêu cầu Kotlin tạo interop() thành một hàm tĩnh trong InteropFish.

Bạn cũng có thể tạo chú thích của riêng mình, nhưng điều này chủ yếu hữu ích nếu bạn đang viết một thư viện cần thông tin cụ thể về các lớp tại thời gian chạy, tức là phản chiếu.

Bước 1: Tạo gói và tệp mới

  1. Trong src, hãy tạo một gói mới, example.
  2. Trong example, hãy tạo một tệp Kotlin mới, Annotations.kt.

Bước 2: Tạo chú thích của riêng bạn

  1. Trong Annotations.kt, hãy tạo một lớp Plant có 2 phương thức là trim()fertilize().
class Plant {
        fun trim(){}
        fun fertilize(){}
}
  1. Tạo một hàm in tất cả các phương thức trong một lớp. Sử dụng ::class để lấy thông tin về một lớp trong thời gian chạy. Sử dụng declaredMemberFunctions để lấy danh sách các phương thức của một lớp. (Để truy cập vào tính năng này, bạn cần nhập kotlin.reflect.full.*)
import kotlin.reflect.full.*    // required import

class Plant {
    fun trim(){}
    fun fertilize(){}
}

fun testAnnotations() {
    val classObj = Plant::class
    for (m in classObj.declaredMemberFunctions) {
        println(m.name)
    }
}
  1. Tạo một hàm main() để gọi quy trình kiểm thử. Chạy chương trình rồi quan sát kết quả.
fun main() {
    testAnnotations()
}
⇒ trim
fertilize
  1. Tạo một chú thích đơn giản, ImAPlant.
annotation class ImAPlant

Thao tác này không làm gì khác ngoài việc cho biết rằng nó đã được chú thích.

  1. Thêm chú giải này vào trước lớp Plant.
@ImAPlant class Plant{
    ...
}
  1. Thay đổi testAnnotations() để in tất cả chú thích của một lớp. Sử dụng annotations để lấy tất cả chú thích của một lớp. Chạy chương trình của bạn và quan sát kết quả.
fun testAnnotations() {
    val plantObject = Plant::class
    for (a in plantObject.annotations) {
        println(a.annotationClass.simpleName)
    }
}
⇒ ImAPlant
  1. Thay đổi testAnnotations() để tìm chú thích ImAPlant. Dùng findAnnotation() để tìm một chú thích cụ thể. Chạy chương trình của bạn và quan sát kết quả.
fun testAnnotations() {
    val plantObject = Plant::class
    val myAnnotationObject = plantObject.findAnnotation<ImAPlant>()
    println(myAnnotationObject)
}
⇒ @example.ImAPlant()

Bước 3: Tạo chú thích có mục tiêu

Chú giải có thể nhắm đến các phương thức getter hoặc setter. Khi đó, bạn có thể áp dụng các giá trị này bằng tiền tố @get: hoặc @set:. Điều này thường xảy ra khi sử dụng các khung có chú thích.

  1. Khai báo 2 chú thích, OnGet chỉ có thể áp dụng cho các phương thức truy xuất thuộc tính và OnSet chỉ có thể áp dụng cho các phương thức thiết lập thuộc tính. Sử dụng @Target(AnnotationTarger.PROPERTY_GETTER) hoặc PROPERTY_SETTER trên mỗi phần.
annotation class ImAPlant

@Target(AnnotationTarget.PROPERTY_GETTER)
annotation class OnGet
@Target(AnnotationTarget.PROPERTY_SETTER)
annotation class OnSet

@ImAPlant class Plant {
    @get:OnGet
    val isGrowing: Boolean = true

    @set:OnSet
    var needsFood: Boolean = false
}

Chú thích thực sự hữu ích khi tạo các thư viện kiểm tra mọi thứ cả trong thời gian chạy và đôi khi trong thời gian biên dịch. Tuy nhiên, mã ứng dụng thông thường chỉ sử dụng chú thích do các khung cung cấp.

Kotlin có một số cách kiểm soát luồng. Bạn đã quen thuộc với return, được trả về từ một hàm đến hàm bao quanh nó. Sử dụng break giống như return, nhưng dành cho các vòng lặp.

Kotlin cung cấp cho bạn thêm quyền kiểm soát đối với các vòng lặp bằng một tính năng gọi là lệnh break có nhãn. Một break đủ điều kiện có nhãn sẽ chuyển đến điểm thực thi ngay sau vòng lặp được đánh dấu bằng nhãn đó. Điều này đặc biệt hữu ích khi xử lý các vòng lặp lồng nhau.

Bạn có thể đánh dấu mọi biểu thức trong Kotlin bằng một nhãn. Nhãn có dạng mã nhận dạng, theo sau là ký hiệu @.

  1. Trong Annotations.kt, hãy thử một lệnh break được gắn nhãn bằng cách thoát khỏi một vòng lặp bên trong.
fun labels() {
    outerLoop@ for (i in 1..100) {
         print("$i ")
         for (j in 1..100) {
             if (i > 10) break@outerLoop  // breaks to outer loop
        }
    }
}

fun main() {
    labels()
}
  1. Chạy chương trình rồi quan sát kết quả.
⇒ 1 2 3 4 5 6 7 8 9 10 11 

Tương tự, bạn có thể dùng continue được gắn nhãn. Thay vì thoát khỏi vòng lặp được gắn nhãn, lệnh continue được gắn nhãn sẽ chuyển sang lần lặp tiếp theo của vòng lặp.

Hàm lambda là hàm ẩn danh, tức là hàm không có tên. Bạn có thể chỉ định các hàm này cho biến và truyền chúng dưới dạng đối số cho các hàm và phương thức. Chúng cực kỳ hữu ích.

Bước 1: Tạo một hàm lambda đơn giản

  1. Khởi động REPL trong IntelliJ IDEA, Tools > Kotlin > Kotlin REPL (Công cụ > Kotlin > Kotlin REPL).
  2. Tạo một lambda có đối số dirty: Int thực hiện phép tính, chia dirty cho 2. Chỉ định hàm lambda cho một biến, waterFilter.
val waterFilter = { dirty: Int -> dirty / 2 }
  1. Gọi waterFilter, truyền giá trị 30.
waterFilter(30)
⇒ res0: kotlin.Int = 15

Bước 2: Tạo một lambda bộ lọc

  1. Vẫn trong REPL, hãy tạo một lớp dữ liệu, Fish, với một thuộc tính, name.
data class Fish(val name: String)
  1. Tạo một danh sách gồm 3 Fish, có tên là Flipper, Moby Dick và Dory.
val myFish = listOf(Fish("Flipper"), Fish("Moby Dick"), Fish("Dory"))
  1. Thêm bộ lọc để kiểm tra những tên có chứa chữ "i".
myFish.filter { it.name.contains("i")}
⇒ res3: kotlin.collections.List<Line_1.Fish> = [Fish(name=Flipper), Fish(name=Moby Dick)]

Trong biểu thức lambda, it đề cập đến phần tử danh sách hiện tại và bộ lọc được áp dụng cho từng phần tử danh sách theo thứ tự.

  1. Áp dụng joinString() cho kết quả, dùng ", " làm dấu phân cách.
myFish.filter { it.name.contains("i")}.joinToString(", ") { it.name }
⇒ res4: kotlin.String = Flipper, Moby Dick

Hàm joinToString() tạo một chuỗi bằng cách kết hợp các tên đã lọc, phân tách bằng chuỗi được chỉ định. Đây là một trong nhiều hàm hữu ích được tích hợp trong thư viện chuẩn của Kotlin.

Việc truyền một lambda hoặc hàm khác làm đối số cho một hàm sẽ tạo ra một hàm bậc cao. Bộ lọc ở trên là một ví dụ đơn giản về điều này. filter() là một hàm và bạn truyền cho hàm này một lambda chỉ định cách xử lý từng phần tử của danh sách.

Viết các hàm bậc cao bằng lambda mở rộng là một trong những phần nâng cao nhất của ngôn ngữ Kotlin. Bạn sẽ mất một thời gian để học cách viết các biểu thức này, nhưng chúng rất thuận tiện khi sử dụng.

Bước 1: Tạo lớp học mới

  1. Trong gói example, hãy tạo một tệp Kotlin mới là Fish.kt.
  2. Trong Fish.kt, hãy tạo một lớp dữ liệu Fish, có một thuộc tính là name.
data class Fish (var name: String)
  1. Tạo hàm fishExamples(). Trong fishExamples(), hãy tạo một con cá có tên là "splashy", tất cả đều là chữ thường.
fun fishExamples() {
    val fish = Fish("splashy")  // all lowercase
}
  1. Tạo một hàm main() gọi fishExamples().
fun main () {
    fishExamples()
}
  1. Biên dịch và chạy chương trình bằng cách nhấp vào hình tam giác màu xanh lục ở bên trái main(). Chưa có đầu ra.

Bước 2: Sử dụng hàm bậc cao

Hàm with() cho phép bạn tạo một hoặc nhiều tham chiếu đến một đối tượng hoặc thuộc tính theo cách ngắn gọn hơn. Sử dụng this. with() thực sự là một hàm bậc cao và trong hàm lambda, bạn chỉ định việc cần làm với đối tượng được cung cấp.

  1. Sử dụng with() để viết hoa tên cá trong fishExamples(). Trong dấu ngoặc nhọn, this đề cập đến đối tượng được truyền đến with().
fun fishExamples() {
    val fish = Fish("splashy")  // all lowercase
    with (fish.name) {
        this.capitalize()
    }
}
  1. Không có đầu ra, vì vậy hãy thêm println() xung quanh đầu ra đó. Và this là ngầm định và không cần thiết, vì vậy bạn có thể xoá nó.
fun fishExamples() {
    val fish = Fish("splashy")  // all lowercase
    with (fish.name) {
        println(capitalize())
    }
}
⇒ Splashy

Bước 3: Tạo một hàm bậc cao

Trong nội bộ, with() là một hàm bậc cao. Để xem cách thức hoạt động của phương pháp này, bạn có thể tạo phiên bản đơn giản hoá rất nhiều của with() chỉ hoạt động cho các chuỗi.

  1. Trong Fish.kt, hãy xác định một hàm myWith() nhận 2 đối số. Các đối số là đối tượng cần thao tác và một hàm xác định thao tác. Quy ước cho tên đối số của hàm là block. Trong trường hợp này, hàm đó không trả về giá trị nào, được chỉ định bằng Unit.
fun myWith(name: String, block: String.() -> Unit) {}

Bên trong myWith(), block() hiện là một hàm mở rộng của String. Lớp được mở rộng thường được gọi là đối tượng nhận. Vì vậy, name là đối tượng nhận trong trường hợp này.

  1. Trong phần nội dung của myWith(), hãy áp dụng hàm đã truyền vào, block(), cho đối tượng nhận, name.
fun myWith(name: String, block: String.() -> Unit) {
    name.block()
}
  1. Trong fishExamples(), hãy thay thế with() bằng myWith().
fun fishExamples() {
    val fish = Fish("splashy")  // all lowercase
    myWith (fish.name) {
        println(capitalize())
    }
}

fish.name là đối số tên và println(capitalize()) là hàm khối.

  1. Chạy chương trình và chương trình sẽ hoạt động như trước.
⇒ Splashy

Bước 4: Khám phá các tiện ích tích hợp khác

Lambda with() mở rộng rất hữu ích và là một phần của Thư viện chuẩn Kotlin. Sau đây là một số API khác mà bạn có thể thấy hữu ích: run(), apply()let().

Hàm run() là một tiện ích hoạt động với mọi loại. Hàm này lấy một lambda làm đối số và trả về kết quả thực thi lambda.

  1. Trong fishExamples(), hãy gọi run() trên fish để lấy tên.
fish.run {
   name
}

Thao tác này chỉ trả về thuộc tính name. Bạn có thể chỉ định giá trị đó cho một biến hoặc in giá trị đó. Đây không phải là một ví dụ hữu ích, vì bạn chỉ cần truy cập vào thuộc tính này, nhưng run() có thể hữu ích cho các biểu thức phức tạp hơn.

Hàm apply() tương tự như run(), nhưng hàm này trả về đối tượng đã thay đổi mà hàm được áp dụng thay vì kết quả của lambda. Điều này có thể hữu ích khi gọi các phương thức trên một đối tượng mới tạo.

  1. Sao chép fish và gọi apply() để đặt tên cho bản sao mới.
val fish2 = Fish(name = "splashy").apply {
     name = "sharky"
}
println(fish2.name)
⇒ sharky

Hàm let() tương tự như apply(), nhưng hàm này trả về một bản sao của đối tượng có các thay đổi. Điều này có thể hữu ích khi bạn muốn kết hợp các thao tác với nhau.

  1. Sử dụng let() để lấy tên của fish, viết hoa tên đó, nối một chuỗi khác vào tên đó, lấy độ dài của kết quả đó, cộng 31 vào độ dài, sau đó in kết quả.
println(fish.let { it.name.capitalize()}
.let{it + "fish"}
.let{it.length}
.let{it + 31})
⇒ 42

Trong ví dụ này, loại đối tượng mà it đề cập đến là Fish, sau đó là String, rồi lại là String và cuối cùng là Int.

  1. In fish sau khi gọi let(), bạn sẽ thấy rằng giá trị này không thay đổi.
println(fish.let { it.name.capitalize()}
    .let{it + "fish"}
    .let{it.length}
    .let{it + 31})
println(fish)
⇒ 42
Fish(name=splashy)

Hàm lambda và các hàm bậc cao hơn rất hữu ích, nhưng bạn cần biết rằng hàm lambda là các đối tượng. Biểu thức lambda là một thực thể của giao diện Function, bản thân giao diện này là một kiểu phụ của Object. Hãy xem xét ví dụ trước về myWith().

myWith(fish.name) {
    capitalize()
}

Giao diện Function có một phương thức là invoke(). Phương thức này bị ghi đè để gọi biểu thức lambda. Nếu viết đầy đủ, mã này sẽ có dạng như mã bên dưới.

// actually creates an object that looks like this
myWith(fish.name, object : Function1<String, Unit> {
    override fun invoke(name: String) {
        name.capitalize()
    }
})

Thông thường, đây không phải là vấn đề, vì việc tạo các đối tượng và gọi các hàm không tốn nhiều chi phí, tức là bộ nhớ và thời gian CPU. Nhưng nếu bạn đang xác định một thứ gì đó như myWith() mà bạn sử dụng ở mọi nơi, thì chi phí có thể tăng lên.

Kotlin cung cấp inline như một cách để xử lý trường hợp này nhằm giảm chi phí trong thời gian chạy bằng cách thêm một chút công việc cho trình biên dịch. (Bạn đã tìm hiểu một chút về inline trong bài học trước nói về các loại được hiện thực hoá.) Việc đánh dấu một hàm là inline có nghĩa là mỗi khi hàm được gọi, trình biên dịch sẽ thực sự chuyển đổi mã nguồn để "đưa vào cùng dòng" hàm đó. Tức là trình biên dịch sẽ thay đổi mã để thay thế hàm lambda bằng các chỉ dẫn bên trong hàm lambda.

Nếu myWith() trong ví dụ trên được đánh dấu bằng inline:

inline myWith(fish.name) {
    capitalize()
}

thì nó sẽ được chuyển đổi thành một lệnh gọi trực tiếp:

// with myWith() inline, this becomes
fish.name.capitalize()

Bạn nên lưu ý rằng việc đưa các hàm lớn vào cùng dòng sẽ làm tăng kích thước mã của bạn, vì vậy, tốt nhất là bạn nên dùng cho các hàm đơn giản được sử dụng nhiều lần như myWith(). Các hàm mở rộng trong những thư viện mà bạn đã tìm hiểu trước đó được đánh dấu là inline, nên bạn không cần lo lắng về việc tạo thêm các đối tượng.

Single Abstract Method (Phương thức trừu tượng đơn) chỉ có nghĩa là một giao diện có một phương thức trên đó. Chúng rất phổ biến khi sử dụng các API được viết bằng ngôn ngữ lập trình Java, vì vậy có một từ viết tắt cho chúng là SAM. Một số ví dụ là Runnable (có một phương thức trừu tượng duy nhất là run()) và Callable (có một phương thức trừu tượng duy nhất là call()).

Trong Kotlin, bạn phải gọi các hàm nhận SAM làm tham số mọi lúc. Hãy thử ví dụ bên dưới.

  1. Trong example, hãy tạo một lớp Java, JavaRun, rồi dán nội dung sau vào tệp.
package example;

public class JavaRun {
    public static void runNow(Runnable runnable) {
        runnable.run();
    }
}

Kotlin cho phép bạn tạo một đối tượng triển khai một giao diện bằng cách đặt object: trước loại. Điều này hữu ích khi truyền các tham số đến SAM.

  1. Quay lại Fish.kt, hãy tạo một hàm runExample() để tạo Runnable bằng object:. Đối tượng này phải triển khai run() bằng cách in "I'm a Runnable".
fun runExample() {
    val runnable = object: Runnable {
        override fun run() {
            println("I'm a Runnable")
        }
    }
}
  1. Gọi JavaRun.runNow() bằng đối tượng bạn đã tạo.
fun runExample() {
    val runnable = object: Runnable {
        override fun run() {
            println("I'm a Runnable")
        }
    }
    JavaRun.runNow(runnable)
}
  1. Gọi runExample() từ main() rồi chạy chương trình.
⇒ I'm a Runnable

Cần rất nhiều công sức để in một nội dung nào đó, nhưng đây là một ví dụ hay về cách hoạt động của SAM. Tất nhiên, Kotlin cung cấp một cách đơn giản hơn để thực hiện việc này: sử dụng một lambda thay cho đối tượng để giúp mã này trở nên gọn gàng hơn nhiều.

  1. Xoá mã hiện có trong runExample, thay đổi mã đó để gọi runNow() bằng một hàm lambda rồi chạy chương trình.
fun runExample() {
    JavaRun.runNow({
        println("Passing a lambda as a Runnable")
    })
}
⇒ Passing a lambda as a Runnable
  1. Bạn có thể làm cho mã này ngắn gọn hơn nữa bằng cách sử dụng cú pháp lệnh gọi tham số cuối cùng và loại bỏ dấu ngoặc đơn.
fun runExample() {
    JavaRun.runNow {
        println("Last parameter is a lambda as a Runnable")
    }
}
⇒ Last parameter is a lambda as a Runnable

Đó là những kiến thức cơ bản về SAM (Phương thức trừu tượng đơn). Bạn có thể khởi tạo, ghi đè và gọi đến SAM bằng một dòng mã, sử dụng mẫu:
Class.singleAbstractMethod { lambda_of_override }

Bài học này đã ôn lại về lambda và đi sâu hơn vào các hàm bậc cao – những phần quan trọng của Kotlin. Bạn cũng đã tìm hiểu về chú giải và điểm ngắt được gắn nhãn.

  • Sử dụng chú thích để chỉ định những việc cần làm cho trình biên dịch. Ví dụ:
    @file:JvmName("Foo")
  • Sử dụng các lệnh ngắt được gắn nhãn để cho phép mã của bạn thoát khỏi bên trong các vòng lặp lồng nhau. Ví dụ:
    if (i > 10) break@outerLoop // breaks to outerLoop label
  • Hàm lambda có thể rất hữu ích khi kết hợp với các hàm bậc cao.
  • Lambda là các đối tượng. Để tránh tạo đối tượng, bạn có thể đánh dấu hàm bằng inline và trình biên dịch sẽ đặt nội dung của lambda trực tiếp vào mã.
  • Hãy sử dụng inline một cách cẩn thận, nhưng nó có thể giúp chương trình của bạn giảm mức sử dụng tài nguyên.
  • SAM (Single Abstract Method) là một mẫu phổ biến và được đơn giản hoá bằng các lambda. Mẫu cơ bản là:
    Class.singleAbstractMethod { lamba_of_override }
  • Thư viện chuẩn Kotlin cung cấp nhiều hàm hữu ích, bao gồm cả một số SAM, vì vậy, hãy tìm hiểu những gì có trong thư viện này.

Kotlin còn nhiều điều thú vị hơn những gì được đề cập trong khoá học này, nhưng giờ đây bạn đã nắm được những kiến thức cơ bản để bắt đầu phát triển các chương trình Kotlin của riêng mình. Hy vọng bạn sẽ hào hứng với ngôn ngữ biểu đạt này và mong muốn tạo ra nhiều chức năng hơn trong khi viết ít mã hơn (đặc biệt nếu bạn đang sử dụng ngôn ngữ lập trình Java). Thực hành và học tập trong quá trình làm việc là cách tốt nhất để trở thành chuyên gia về Kotlin. Vì vậy, hãy tiếp tục khám phá và tự học về Kotlin.

Tài liệu về Kotlin

Nếu bạn muốn biết thêm thông tin về bất kỳ chủ đề nào trong khoá học này hoặc nếu bạn gặp khó khăn, thì https://kotlinlang.org là nơi tốt nhất để bạn bắt đầu.

Hướng dẫn về Kotlin

Trang web https://try.kotlinlang.org có các hướng dẫn phong phú được gọi là Kotlin Koans, một trình thông dịch dựa trên web và một bộ tài liệu tham khảo đầy đủ kèm theo ví dụ.

Khoá học của Udacity

Để xem khoá học của Udacity về chủ đề này, hãy xem Chương trình đào tạo về Kotlin dành cho lập trình viên.

IntelliJ IDEA

Bạn có thể xem tài liệu về IntelliJ IDEA trên trang web của JetBrains.

Thư viện chuẩn Kotlin

Thư viện chuẩn Kotlin cung cấp nhiều hàm hữu ích. Trước khi bạn viết hàm hoặc giao diện của riêng mình, hãy luôn kiểm tra Thư viện chuẩn để xem có ai đã giúp bạn làm một số việc hay không. Thỉnh thoảng, hãy quay lại đây để kiểm tra vì chúng tôi thường xuyên thêm chức năng mới.

Hướng dẫn về Kotlin

Trang web https://try.kotlinlang.org có các hướng dẫn phong phú được gọi là Kotlin Koans, một trình thông dịch dựa trên web và một bộ tài liệu tham khảo đầy đủ kèm theo ví dụ.

Khoá học của Udacity

Để xem khoá học của Udacity về chủ đề này, hãy xem Chương trình đào tạo về Kotlin dành cho lập trình viên.

IntelliJ IDEA

Bạn có thể xem tài liệu về IntelliJ IDEA trên trang web của JetBrains.

Phần này liệt kê các bài tập về nhà cho học viên của lớp học lập trình này trong phạm vi khoá học có người hướng dẫn. Người hướng dẫn phải thực hiện các việc sau đây:

  • Giao bài tập về nhà nếu cần.
  • Trao đổi với học viên về cách nộp bài tập về nhà.
  • Chấm điểm bài tập về nhà.

Người hướng dẫn có thể sử dụng các đề xuất này ít hoặc nhiều tuỳ ý và nên giao cho học viên bất kỳ bài tập về nhà nào khác mà họ cảm thấy phù hợp.

Nếu bạn đang tự học các lớp học lập trình, hãy sử dụng những bài tập về nhà này để kiểm tra kiến thức của mình.

Trả lời các câu hỏi sau

Câu hỏi 1

Trong Kotlin, SAM là viết tắt của:

▢ So khớp đối số an toàn

▢ Phương thức truy cập đơn giản

▢ Phương thức trừu tượng đơn

▢ Phương pháp truy cập chiến lược

Câu hỏi 2

Hàm mở rộng nào sau đây không phải là hàm mở rộng Thư viện chuẩn Kotlin?

elvis()

apply()

run()

with()

Câu hỏi 3

Câu nào sau đây không đúng về lambda trong Kotlin?

▢ Lambda là hàm ẩn danh.

▢ Biểu thức lambda là các đối tượng, trừ phi được nội tuyến.

▢ Lambda tiêu tốn nhiều tài nguyên và không nên được sử dụng.

▢ Bạn có thể truyền hàm lambda đến các hàm khác.

Câu hỏi 4

Nhãn trong Kotlin được biểu thị bằng một giá trị nhận dạng, theo sau là:

:

::

@:

@

Xin chúc mừng! Bạn đã hoàn thành lớp học lập trình Kotlin Bootcamp dành cho lập trình viên.

Để biết thông tin tổng quan về khoá học này, bao gồm cả đường liên kết đến các lớp học lập trình khác, hãy xem "Chương trình đào tạo về Kotlin dành cho lập trình viên: Chào mừng bạn đến với khoá học".