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
Trong lớp học lập trình này, bạn sẽ được giới thiệu về các lớp, hàm và phương thức chung, cũng như cách chúng hoạt động trong 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 bạn sẽ học được
- Cách sử dụng các lớp, phương thức và hàm chung
Bạn sẽ thực hiện
- Tạo một lớp chung và thêm các ràng buộc
- Tạo các loại
invàout - Tạo các hàm, phương thức và hàm mở rộng chung
Giới thiệu về kiểu chung
Kotlin, giống như nhiều ngôn ngữ lập trình, có các kiểu chung. Loại chung cho phép bạn tạo một lớp chung, nhờ đó giúp lớp này linh hoạt hơn nhiều.
Hãy tưởng tượng bạn đang triển khai một lớp MyList chứa danh sách các mục. Nếu không có kiểu chung, bạn sẽ cần triển khai một phiên bản mới của MyList cho từng loại: một phiên bản cho Double, một phiên bản cho String và một phiên bản cho Fish. Với kiểu chung, bạn có thể tạo danh sách chung để lưu trữ mọi loại đối tượng. Giống như việc biến kiểu thành một ký tự đại diện phù hợp với nhiều kiểu.
Để xác định một loại chung, hãy đặt T trong dấu ngoặc nhọn <T> sau tên lớp. (Bạn có thể sử dụng một chữ cái khác hoặc tên dài hơn, nhưng quy ước cho một loại chung là T.)
class MyList<T> {
fun get(pos: Int): T {
TODO("implement")
}
fun addItem(item: T) {}
}Bạn có thể tham chiếu T như thể đó là một loại thông thường. Loại dữ liệu trả về cho get() là T và tham số cho addItem() thuộc loại T. Tất nhiên, danh sách chung rất hữu ích, vì vậy, lớp List được tích hợp vào Kotlin.
Bước 1: Tạo một hệ phân cấp kiểu
Trong bước này, bạn sẽ tạo một số lớp để sử dụng trong bước tiếp theo. Chúng ta đã đề cập đến việc phân lớp con trong một lớp học lập trình trước đây, nhưng đây là phần tóm tắt ngắn gọn.
- Để giữ cho ví dụ này không bị lộn xộn, hãy tạo một gói mới trong src và gọi gói đó là
generics. - Trong gói generics, hãy tạo một tệp
Aquarium.ktmới. Điều này cho phép bạn xác định lại mọi thứ bằng cách sử dụng cùng tên mà không bị xung đột, vì vậy, phần còn lại của mã cho lớp học lập trình này sẽ nằm trong tệp này. - Tạo một hệ phân cấp kiểu cho các loại nguồn cung cấp nước. Bắt đầu bằng cách tạo
WaterSupplythành một lớpopenđể có thể phân lớp con. - Thêm tham số boolean
var,needsProcessing. Thao tác này sẽ tự động tạo một thuộc tính có thể thay đổi, cùng với một getter và setter. - Tạo một lớp con
TapWatermở rộngWaterSupplyvà truyềntruechoneedsProcessing, vì nước máy có chứa các chất phụ gia có hại cho cá. - Trong
TapWater, hãy xác định một hàm có tên làaddChemicalCleaners()đặtneedsProcessingthànhfalsesau khi làm sạch nước. Bạn có thể đặt thuộc tínhneedsProcessingtừTapWatervì theo mặc định, thuộc tính này làpublicvà có thể truy cập vào các lớp con. Sau đây là mã hoàn chỉnh.
package generics
open class WaterSupply(var needsProcessing: Boolean)
class TapWater : WaterSupply(true) {
fun addChemicalCleaners() {
needsProcessing = false
}
}- Tạo thêm hai lớp con của
WaterSupply, có tên làFishStoreWatervàLakeWater.FishStoreWaterkhông cần xử lý, nhưngLakeWaterphải được lọc bằng phương thứcfilter(). Sau khi lọc, dữ liệu không cần được xử lý lại, vì vậy trongfilter(), hãy đặtneedsProcessing = false.
class FishStoreWater : WaterSupply(false)
class LakeWater : WaterSupply(true) {
fun filter() {
needsProcessing = false
}
}Nếu bạn cần thêm thông tin, hãy xem lại bài học trước về tính kế thừa trong Kotlin.
Bước 2: Tạo một lớp chung
Trong bước này, bạn sẽ sửa đổi lớp Aquarium để hỗ trợ nhiều loại nguồn cung cấp nước.
- Trong Aquarium.kt, hãy xác định một lớp
Aquarium, có<T>trong dấu ngoặc sau tên lớp. - Thêm một thuộc tính không thể thay đổi
waterSupplythuộc loạiTvàoAquarium.
class Aquarium<T>(val waterSupply: T)- Viết một hàm có tên là
genericsExample(). Hàm này không thuộc một lớp nào, nên có thể nằm ở cấp cao nhất của tệp, chẳng hạn như hàmmain()hoặc các định nghĩa lớp. Trong hàm, hãy tạo mộtAquariumrồi truyềnWaterSupplyvào. Vì tham sốwaterSupplylà tham số chung, nên bạn phải chỉ định loại trong cặp dấu ngoặc nhọn<>.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
}- Trong
genericsExample(), mã của bạn có thể truy cập vàowaterSupplycủa hồ cá. Vì thuộc tính này thuộc loạiTapWater, nên bạn có thể gọiaddChemicalCleaners()mà không cần truyền kiểu.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
aquarium.waterSupply.addChemicalCleaners()
}- Khi tạo đối tượng
Aquarium, bạn có thể xoá dấu ngoặc nhọn và nội dung giữa các dấu ngoặc này vì Kotlin có khả năng dự đoán loại. Vì vậy, bạn không cần nóiTapWaterhai lần khi tạo phiên bản. Loại này có thể được suy luận bằng đối số thànhAquarium; loại này vẫn sẽ tạo ra mộtAquariumthuộc loạiTapWater.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
aquarium.waterSupply.addChemicalCleaners()
}- Để xem điều gì đang xảy ra, hãy in
needsProcessingtrước và sau khi gọiaddChemicalCleaners(). Dưới đây là hàm hoàn chỉnh.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
aquarium.waterSupply.addChemicalCleaners()
println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
}- Thêm một hàm
main()để gọigenericsExample(), sau đó chạy chương trình và quan sát kết quả.
fun main() {
genericsExample()
}⇒ water needs processing: true water needs processing: false
Bước 3: Nêu cụ thể hơn
Chung chung có nghĩa là bạn có thể truyền hầu hết mọi thứ và đôi khi đó là một vấn đề. Ở bước này, bạn sẽ làm cho lớp Aquarium cụ thể hơn về những gì bạn có thể đưa vào đó.
- Trong
genericsExample(), hãy tạo mộtAquarium, truyền một chuỗi chowaterSupply, sau đó in thuộc tínhwaterSupplycủa hồ cá.
fun genericsExample() {
val aquarium2 = Aquarium("string")
println(aquarium2.waterSupply)
}- Chạy chương trình của bạn và quan sát kết quả.
⇒ string
Kết quả là chuỗi bạn đã truyền, vì Aquarium không đặt bất kỳ giới hạn nào đối với T.Bạn có thể truyền bất kỳ loại nào, kể cả String.
- Trong
genericsExample(), hãy tạo mộtAquariumkhác, truyềnnullchowaterSupply. NếuwaterSupplylà giá trị rỗng, hãy xuất"waterSupply is null".
fun genericsExample() {
val aquarium3 = Aquarium(null)
if (aquarium3.waterSupply == null) {
println("waterSupply is null")
}
}- Chạy chương trình của bạn và quan sát kết quả.
⇒ waterSupply is null
Tại sao bạn có thể truyền null khi tạo Aquarium? Điều này có thể xảy ra vì theo mặc định, T là loại Any? có thể nhận giá trị rỗng, loại ở đầu hệ thống phân cấp loại. Nội dung sau đây tương đương với nội dung bạn đã nhập trước đó.
class Aquarium<T: Any?>(val waterSupply: T)- Để không cho phép truyền
null, hãy tạoTthuộc loạiAnymột cách rõ ràng bằng cách xoá?sauAny.
class Aquarium<T: Any>(val waterSupply: T)Trong ngữ cảnh này, Any được gọi là ràng buộc chung. Điều này có nghĩa là bạn có thể truyền bất kỳ loại nào cho T miễn là loại đó không phải là null.
- Điều bạn thực sự muốn là đảm bảo rằng chỉ có
WaterSupply(hoặc một trong các lớp con của lớp này) mới có thể được truyền choT. Thay thếAnybằngWaterSupplyđể xác định một ràng buộc chung cụ thể hơn.
class Aquarium<T: WaterSupply>(val waterSupply: T)Bước 4: Thêm các bước kiểm tra khác
Trong bước này, bạn sẽ tìm hiểu về hàm check() để đảm bảo mã của bạn hoạt động như mong đợi. Hàm check() là một hàm thư viện chuẩn trong Kotlin. Hàm này hoạt động như một câu khẳng định và sẽ gửi một IllegalStateException nếu đối số của hàm được đánh giá là false.
- Thêm phương thức
addWater()vào lớpAquariumđể thêm nước, vớicheck()đảm bảo bạn không cần xử lý nước trước.
class Aquarium<T: WaterSupply>(val waterSupply: T) {
fun addWater() {
check(!waterSupply.needsProcessing) { "water supply needs processing first" }
println("adding water from $waterSupply")
}
}Trong trường hợp này, nếu needsProcessing là true, check() sẽ gửi một ngoại lệ.
- Trong
genericsExample(), hãy thêm mã để tạo mộtAquariumcóLakeWater, sau đó thêm một ít nước vào đó.
fun genericsExample() {
val aquarium4 = Aquarium(LakeWater())
aquarium4.addWater()
}- Chạy chương trình của bạn và bạn sẽ gặp phải một ngoại lệ, vì nước cần được lọc trước.
⇒ Exception in thread "main" java.lang.IllegalStateException: water supply needs processing first
at Aquarium.generics.Aquarium.addWater(Aquarium.kt:21)- Thêm một lệnh gọi để lọc nước trước khi thêm nước vào
Aquarium. Giờ đây, khi bạn chạy chương trình, sẽ không có ngoại lệ nào được đưa ra.
fun genericsExample() {
val aquarium4 = Aquarium(LakeWater())
aquarium4.waterSupply.filter()
aquarium4.addWater()
}⇒ adding water from generics.LakeWater@880ec60
Phần trên trình bày những kiến thức cơ bản về kiểu chung. Các tác vụ sau đây bao gồm nhiều nội dung hơn, nhưng khái niệm quan trọng là cách khai báo và sử dụng một lớp chung với một ràng buộc chung.
Trong nhiệm vụ này, bạn sẽ tìm hiểu về các loại đầu vào và đầu ra bằng các giá trị chung. Kiểu in là kiểu chỉ có thể được truyền vào một lớp chứ không được trả về. Loại out là loại chỉ có thể được trả về từ một lớp.
Hãy xem lớp Aquarium, bạn sẽ thấy rằng kiểu chung chỉ được trả về khi nhận thuộc tính waterSupply. Không có phương thức nào lấy giá trị thuộc loại T làm tham số (ngoại trừ việc xác định giá trị đó trong hàm dựng). Kotlin cho phép bạn xác định các loại out cho chính trường hợp này và có thể suy luận thêm thông tin về những nơi có thể sử dụng các loại một cách an toàn. Tương tự, bạn có thể xác định các loại in cho các loại chung chỉ được truyền vào các phương thức chứ không được trả về. Điều này cho phép Kotlin thực hiện các bước kiểm tra bổ sung để đảm bảo an toàn cho mã.
Các kiểu in và out là chỉ thị cho hệ thống kiểu của Kotlin. Việc giải thích toàn bộ hệ thống kiểu nằm ngoài phạm vi của khoá huấn luyện này (khá phức tạp); tuy nhiên, trình biên dịch sẽ gắn cờ các kiểu không được đánh dấu in và out một cách thích hợp, vì vậy bạn cần biết về các kiểu này.
Bước 1: Xác định loại đầu ra
- Trong lớp
Aquarium, hãy thay đổiT: WaterSupplythành loạiout.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
...
}- Trong cùng một tệp, bên ngoài lớp, hãy khai báo một hàm
addItemTo()dự kiến có mộtAquariumcủaWaterSupply.
fun addItemTo(aquarium: Aquarium<WaterSupply>) = println("item added")- Gọi
addItemTo()từgenericsExample()và chạy chương trình.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
addItemTo(aquarium)
}⇒ item added
Kotlin có thể đảm bảo rằng addItemTo() sẽ không làm gì đó không an toàn về kiểu với WaterSupply chung, vì nó được khai báo là kiểu out.
- Nếu bạn xoá từ khoá
out, trình biên dịch sẽ báo lỗi khi gọiaddItemTo(), vì Kotlin không thể đảm bảo rằng bạn không làm bất cứ điều gì không an toàn với loại này.
Bước 2: Xác định một loại đầu vào
Loại in tương tự như loại out, nhưng đối với các loại chung chỉ được truyền vào hàm chứ không được trả về. Nếu cố gắng trả về một kiểu in, bạn sẽ gặp lỗi trình biên dịch. Trong ví dụ này, bạn sẽ xác định một loại in trong giao diện.
- Trong Aquarium.kt, hãy xác định một giao diện
Cleanernhận mộtTchung bị hạn chế thànhWaterSupply. Vì chỉ được dùng làm đối số choclean(), nên bạn có thể đặt tham số này làin.
interface Cleaner<in T: WaterSupply> {
fun clean(waterSupply: T)
}- Để sử dụng giao diện
Cleaner, hãy tạo một lớpTapWaterCleanertriển khaiCleanerđể làm sạchTapWaterbằng cách thêm hoá chất.
class TapWaterCleaner : Cleaner<TapWater> {
override fun clean(waterSupply: TapWater) = waterSupply.addChemicalCleaners()
}- Trong lớp
Aquarium, hãy cập nhậtaddWater()để lấyCleanerthuộc loạiTvà làm sạch nước trước khi thêm.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
fun addWater(cleaner: Cleaner<T>) {
if (waterSupply.needsProcessing) {
cleaner.clean(waterSupply)
}
println("water added")
}
}- Cập nhật mã ví dụ
genericsExample()để tạoTapWaterCleaner,AquariumbằngTapWater, sau đó thêm một ít nước bằng chất tẩy rửa. Thiết bị sẽ sử dụng chất tẩy rửa khi cần.
fun genericsExample() {
val cleaner = TapWaterCleaner()
val aquarium = Aquarium(TapWater())
aquarium.addWater(cleaner)
}Kotlin sẽ sử dụng thông tin về kiểu in và out để đảm bảo mã của bạn sử dụng các thành phần chung một cách an toàn. Out và in rất dễ nhớ: Các loại out có thể được truyền ra ngoài dưới dạng giá trị trả về, các loại in có thể được truyền vào trong dưới dạng đối số.

Nếu bạn muốn tìm hiểu kỹ hơn về các loại vấn đề mà các loại và loại ngoài giải quyết, thì tài liệu này sẽ đề cập đến chúng một cách chi tiết.
Trong nhiệm vụ này, bạn sẽ tìm hiểu về các hàm chung và thời điểm nên sử dụng các hàm đó. Thông thường, bạn nên tạo một hàm chung bất cứ khi nào hàm lấy một đối số của lớp có kiểu chung.
Bước 1: Tạo một hàm chung
- Trong generics/Aquarium.kt, hãy tạo một hàm
isWaterClean()nhậnAquarium. Bạn cần chỉ định kiểu chung của tham số; một lựa chọn là sử dụngWaterSupply.
fun isWaterClean(aquarium: Aquarium<WaterSupply>) {
println("aquarium water is clean: ${aquarium.waterSupply.needsProcessing}")
}Nhưng điều này có nghĩa là Aquarium phải có một tham số loại out để được gọi. Đôi khi out hoặc in quá hạn chế vì bạn cần sử dụng một loại cho cả đầu vào và đầu ra. Bạn có thể xoá yêu cầu out bằng cách tạo hàm chung.
- Để tạo hàm chung, hãy đặt dấu ngoặc nhọn sau từ khoá
funvới kiểu chungTvà mọi ràng buộc, trong trường hợp này làWaterSupply. Thay đổiAquariumđể bị hạn chế bởiTthay vìWaterSupply.
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) {
println("aquarium water is clean: ${!aquarium.waterSupply.needsProcessing}")
}T là một tham số loại cho isWaterClean() đang được dùng để chỉ định loại chung của bể cá. Mẫu này rất phổ biến và bạn nên dành chút thời gian để tìm hiểu.
- Gọi hàm
isWaterClean()bằng cách chỉ định loại trong dấu ngoặc nhọn ngay sau tên hàm và trước dấu ngoặc đơn.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
isWaterClean<TapWater>(aquarium)
}- Vì suy luận kiểu dữ liệu từ đối số
aquarium, nên bạn không cần kiểu dữ liệu này, hãy xoá kiểu dữ liệu đó. Chạy chương trình rồi quan sát kết quả.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
isWaterClean(aquarium)
}⇒ aquarium water is clean: false
Bước 2: Tạo một phương thức chung với kiểu được cụ thể hoá
Bạn cũng có thể dùng các hàm chung cho các phương thức, ngay cả trong những lớp có kiểu chung riêng. Ở bước này, bạn sẽ thêm một phương thức chung vào Aquarium để kiểm tra xem phương thức đó có thuộc loại WaterSupply hay không.
- Trong lớp
Aquarium, hãy khai báo một phương thứchasWaterSupplyOfType()nhận một tham số chungR(Tđã được dùng) bị hạn chế thànhWaterSupplyvà trả vềtruenếuwaterSupplythuộc loạiR. Điều này tương tự như hàm mà bạn đã khai báo trước đó, nhưng nằm bên trong lớpAquarium.
fun <R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R- Lưu ý rằng
Rcuối cùng được gạch chân bằng màu đỏ. Di con trỏ lên biểu tượng đó để xem lỗi là gì.
- Để thực hiện kiểm tra
is, bạn cần cho Kotlin biết rằng kiểu này là reified (cụ thể) và có thể dùng trong hàm. Để làm như vậy, hãy đặtinlinetrước từ khoáfunvàreifiedtrước loại chungR.
inline fun <reified R: WaterSupply> hasWaterSupplyOfType() = waterSupply is RSau khi một kiểu được cụ thể hoá, bạn có thể sử dụng kiểu đó như một kiểu thông thường vì đó là một kiểu thực sau khi được nội tuyến. Điều đó có nghĩa là bạn có thể thực hiện các lượt kiểm tra is bằng cách sử dụng loại.
Nếu bạn không sử dụng reified ở đây, loại này sẽ không đủ "thực" để Kotlin cho phép kiểm tra is. Đó là vì các kiểu không được cụ thể hoá chỉ có sẵn tại thời điểm biên dịch và chương trình của bạn không thể sử dụng các kiểu này tại thời gian chạy. Vấn đề này sẽ được thảo luận thêm trong phần tiếp theo.
- Truyền
TapWaterlàm loại. Tương tự như khi gọi các hàm chung, hãy gọi các phương thức chung bằng cách sử dụng dấu ngoặc nhọn với kiểu sau tên hàm. Chạy chương trình của bạn và quan sát kết quả.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.hasWaterSupplyOfType<TapWater>()) // true
}⇒ true
Bước 3: Tạo các hàm mở rộng
Bạn cũng có thể sử dụng các loại được hiện thực hoá cho các hàm thông thường và hàm mở rộng.
- Bên ngoài lớp
Aquarium, hãy xác định một hàm mở rộng trênWaterSupplycó tên làisOfType(). Hàm này sẽ kiểm tra xemWaterSupplyđã truyền có thuộc một loại cụ thể hay không, chẳng hạn nhưTapWater.
inline fun <reified T: WaterSupply> WaterSupply.isOfType() = this is T- Gọi hàm mở rộng giống như một phương thức.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.waterSupply.isOfType<TapWater>())
}⇒ true
Với các hàm mở rộng này, không quan trọng Aquarium thuộc loại nào (Aquarium hoặc TowerTank hoặc một số lớp con khác), miễn là đó là một Aquarium. Việc sử dụng cú pháp star-projection là một cách thuận tiện để chỉ định nhiều kết quả trùng khớp. Và khi bạn sử dụng một phép chiếu sao, Kotlin cũng sẽ đảm bảo bạn không làm bất cứ điều gì không an toàn.
- Để sử dụng phép chiếu sao, hãy đặt
<*>sauAquarium. Di chuyểnhasWaterSupplyOfType()để trở thành một hàm mở rộng, vì hàm này không thực sự thuộc API cốt lõi củaAquarium.
inline fun <reified R: WaterSupply> Aquarium<*>.hasWaterSupplyOfType() = waterSupply is R- Thay đổi lệnh gọi thành
hasWaterSupplyOfType()rồi chạy chương trình.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.hasWaterSupplyOfType<TapWater>())
}⇒ true
Trong ví dụ trước, bạn phải đánh dấu kiểu chung là reified và tạo hàm inline, vì Kotlin cần biết về các kiểu chung này tại thời gian chạy, chứ không chỉ tại thời gian biên dịch.
Tất cả các kiểu chung chỉ được Kotlin sử dụng trong thời gian biên dịch. Điều này giúp trình biên dịch đảm bảo rằng bạn đang làm mọi việc một cách an toàn. Theo thời gian chạy, tất cả các loại chung đều bị xoá, do đó, thông báo lỗi trước đó về việc kiểm tra một loại đã xoá.
Hoá ra trình biên dịch có thể tạo mã chính xác mà không cần giữ các kiểu chung cho đến thời gian chạy. Nhưng điều này có nghĩa là đôi khi bạn làm một việc gì đó, chẳng hạn như is kiểm tra các loại chung, mà trình biên dịch không thể hỗ trợ. Đó là lý do Kotlin thêm các loại đã sửa đổi hoặc loại thực.
Bạn có thể đọc thêm về các loại được hiện thực hoá và việc xoá kiểu trong tài liệu về Kotlin.
Bài học này tập trung vào kiểu chung, đây là những kiểu quan trọng để giúp mã linh hoạt hơn và dễ tái sử dụng hơn.
- Tạo các lớp chung để giúp mã linh hoạt hơn.
- Thêm các điều kiện ràng buộc chung để giới hạn các loại được dùng với kiểu chung.
- Sử dụng các kiểu
invàoutvới kiểu chung để cung cấp tính năng kiểm tra kiểu tốt hơn nhằm hạn chế các kiểu được truyền vào hoặc trả về từ các lớp. - Tạo các hàm và phương thức chung để làm việc với các kiểu chung. Ví dụ:
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) { ... } - Sử dụng các hàm mở rộng chung để thêm chức năng không phải là chức năng cốt lõi vào một lớp.
- Đôi khi, các loại được cụ thể hoá là cần thiết do việc xoá kiểu. Các loại được cụ thể hoá, không giống như các loại chung, vẫn tồn tại trong thời gian chạy.
- Sử dụng hàm
check()để xác minh rằng mã của bạn đang chạy như dự kiến. Ví dụ:check(!waterSupply.needsProcessing) { "water supply needs processing first" }
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.
- Các thành phần chung
- Hạn chế chung
- Dự đoán hiệu suất
Invàoutloại- Tham số cụ thể hoá
- Xoá kiểu
- Hàm
check()
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 những câu hỏi này
Câu hỏi 1
Đâu là quy ước đặt tên cho một kiểu chung?
▢ <Gen>
▢ <Generic>
▢ <T>
▢ <X>
Câu hỏi 2
Một hạn chế về các loại được phép cho một loại chung được gọi là:
▢ quy định hạn chế chung
▢ một ràng buộc chung
▢ phân định nghĩa
▢ giới hạn kiểu chung
Câu hỏi 3
Cụ thể hoá có nghĩa là:
▢ Tác động thực tế của việc thực thi một đối tượng đã được tính toán.
▢ Đã đặt chỉ mục mục nhập bị hạn chế trên lớp.
▢ Tham số loại chung đã được chuyển thành một loại thực.
▢ Đã kích hoạt chỉ báo lỗi từ xa.
Chuyển sang bài học tiếp theo:
Để 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".