Trong bài này, bạn sẽ tìm hiểu về khai báo đối tượng (singleton) và biểu thức đối tượng với sự trợ giúp của các ví dụ.

1. Khai báo đối tượng

Singleton là một mẫu hướng đối tượng trong đó một class chỉ có thể có một instance (đối tượng).

Ví dụ: bạn đang làm việc một ứng dụng có backend cơ sở dữ liệu SQL. Bạn muốn tạo một nhóm kết nối để truy cập cơ sở dữ liệu trong khi sử dụng lại cùng một kết nối cho tất cả các máy khách. Để làm điều này, bạn có thể tạo kết nối thông qua class singleton để mọi máy khách có thể có cùng một kết nối.

Kotlin cung cấp một cách dễ dàng để tạo các singleton bằng cách sử dụng tính năng khai báo đối tượng. Để làm được điều đó, chúng ta sử dụng từ khóa object.

object SingletonExample {
    ... .. ...
    // body of class
    ... .. ...
}

Đoạn code trên kết hợp khai báo class và khai báo một instance duy nhất của class là SingletonExample.

Một khai báo đối tượng có thể chứa các thuộc tính, hàm, v.v. Tuy nhiên, chúng không được phép có các hàm tạo (điều này có một ý nghĩa). Tại sao lại như vậy?

Tương tự như các đối tượng của một class bình thường, bạn có thể gọi các hàm và truy cập các thuộc tính bằng cách sử dụng ký hiệu “.”.

Ví dụ: Khai báo đối tượng

/*
Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
@author cafedevn
Contact: cafedevn@gmail.com
Fanpage: https://www.facebook.com/cafedevn
Group: https://www.facebook.com/groups/cafedev.vn/
Instagram: https://instagram.com/cafedevn
Twitter: https://twitter.com/CafedeVn
Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
Pinterest: https://www.pinterest.com/cafedevvn/
YouTube: https://www.youtube.com/channel/UCE7zpY_SlHGEgo67pHxqIoA/
*/

object Test {
    private var a: Int = 0
    var b: Int = 1

    fun makeMe12(): Int {
        a = 12
        return a
    }
}

fun main(args: Array<String>) {
    val result: Int

    result = Test.makeMe12()

    println("b = ${Test.b}")
    println("result = $result")
}

Khi bạn chạy chương trình, kết quả sẽ là:

b = 1
result = 12

Khai báo đối tượng có thể kế thừa từ các class và interface theo cách tương tự như các class bình thường.

2. Singletons và tiêm phụ thuộc

Khai báo đối tượng đôi khi có thể hữu ích. Tuy nhiên, chúng không lý tưởng trong các hệ thống phần mềm lớn tương tác với nhiều phần khác của hệ thống.

Bài đọc được đề xuất: Dependency Injection & Singleton Design pattern

3. Biểu thức đối tượng trong Kotlin

Từ khóa object cũng có thể được sử dụng để tạo các đối tượng của một class ẩn danh, được gọi là các đối tượng ẩn danh. Chúng được sử dụng nếu bạn cần tạo một đối tượng có một số sửa đổi nhỏ từ một số class hoặc interface mà không cần khai báo một subclass cho nó. Ví dụ ,

window.addMouseListener(object : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) {
        // ...
    }

    override fun mouseEntered(e: MouseEvent) {
        // ...
    }
})

(Ví dụ được lấy từ trang tài liệu chính thức của Kotlin .)

Ở đây, một đối tượng ẩn danh được khai báo là class mở rộng MouseAdapter.Chương trình ghi đè hai hàm MouseAdapter: hàm mouseClicked() và mouseEntered().

Nếu cần, bạn có thể gán tên cho đối tượng ẩn danh và lưu trữ nó trong một biến. Ví dụ,

val obj = object : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) {
        // ...
    }

    override fun mouseEntered(e: MouseEvent) {
        // ...
    }
}

Ví dụ: Biểu thức đối tượng trong Kotlin

open class Person() {
    fun eat() = println("Eating food.")

    fun talk() = println("Talking with people.")

    open fun pray() = println("Praying god.")
}

fun main(args: Array<String>) {
    val atheist = object : Person() {
        override fun pray() = println("I don't pray. I am an atheist.")
    }

    atheist.eat()
    atheist.talk()
    atheist.pray()
}

Khi bạn chạy chương trình, kết quả sẽ là:

Eating food.
Talking with people.
I don't pray. I am an atheist.

Ở đây, đối tượng ẩn danh được lưu trữ trong biến atheist, biến này triển khai class Person có hàm pray() bị ghi đè.

Nếu bạn đang triển khai một class có hàm tạo để khai báo một đối tượng ẩn danh, bạn cần phải truyền các tham số hàm tạo thích hợp. Ví dụ,

open class Person(name: String, age: Int) {

    init {
        println("name: $name, age: $age")
    }

    fun eat() = println("Eating food.")
    fun talk() = println("Talking with people.")
    open fun pray() = println("Praying god.")
}

fun main(args: Array<String>) {
    val atheist = object : Person("Jack", 29) {
        override fun pray() = println("I don't pray. I am an atheist.")
    }

    atheist.eat()
    atheist.talk()
    atheist.pray()
}

Khi bạn chạy chương trình, kết quả sẽ là:

name: Jack, age: 29
Eating food.
Talking with people.
I don't pray. I am an atheist.

Tài liệu từ cafedev:

Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:

Chào thân ái và quyết thắng!

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!