Các trường của 1 đối tượng là gì năm 2024

Các lớp cung cấp bản thiết kế để tạo dựng đối tượng. Đối tượng là một thực thể của lớp bao gồm dữ liệu dành riêng cho đối tượng đó. Bạn có thể dùng các đối tượng hoặc thực thể lớp thay thế cho nhau.

Tương tự như vậy, hãy tưởng tượng bạn đang xây một ngôi nhà. Giống như bản vẽ của kiến trúc sư, lớp còn được gọi là bản thiết kế. Bản thiết kế tự thân nó không phải là một ngôi nhà mà là hướng dẫn về cách xây nhà. Ngôi nhà là vật thể thực hoặc là một đối tượng được xây dựng dựa trên bản thiết kế.

Giống như bản thiết kế nhà, có nhiều phòng được thiết kế với mục đích sử dụng riêng, mỗi phòng có thiết kế và mục đích riêng. Để biết cách thiết kế các lớp, bạn cần làm quen với cách lập trình hướng đối tượng [OOP], một khung hướng dẫn bạn đóng gói dữ liệu, logic và hành vi vào trong đối tượng.

OOP giúp bạn đơn giản hoá các vấn đề phức tạp trong thế giới thực thành những đối tượng nhỏ hơn. Có bốn khái niệm cơ bản về OOP mà bạn sẽ tìm hiểu thêm trong lớp học lập trình này:

  • Đóng gói. Bao gồm các thuộc tính và phương thức liên quan giúp thực hiện hành động trên các thuộc tính đó trong một lớp. Lấy điện thoại di động của bạn làm ví dụ. Sản phẩm này bao gồm một máy ảnh, màn hình, thẻ nhớ cùng một số phần cứng và phần mềm khác. Bạn không cần phải lo lắng về cách các thành phần bên trong kết hợp với nhau.
  • Tính trừu tượng. Là phần mở rộng của việc đóng gói. Với mục đích là ẩn logic triển khai bên trong càng nhiều càng tốt. Ví dụ: để chụp ảnh bằng điện thoại di động, bạn chỉ cần mở ứng dụng máy ảnh, hướng điện thoại đến nơi muốn chụp và nhấp vào nút để chụp ảnh. Bạn không cần phải biết cách phát triển ứng dụng máy ảnh hoặc phần cứng máy ảnh trên điện thoại di động thực tế hoạt động như thế nào. Tóm lại, cơ chế nội bộ của ứng dụng máy ảnh và cách máy ảnh trên thiết bị di động chụp ảnh sẽ được tóm tắt để bạn thực hiện các tác vụ cần thiết.
  • Tính kế thừa [inheritance]. Cho phép bạn tạo lớp dựa trên đặc điểm và hành vi của các lớp khác bằng cách thiết lập mối quan hệ cha-con. Ví dụ: có nhiều nhà sản xuất chế tạo ra nhiều thiết bị di động chạy Android OS nhưng giao diện người dùng cho từng thiết bị là khác nhau. Nói cách khác, nhà sản xuất kế thừa tính năng của hệ điều hành Android và tuỳ chỉnh dựa trên tính năng đó.
  • Tính đa hình. Từ này được phỏng theo và có nguồn gốc từ Hy Lạp poly-, có nghĩa là nhiều, và -morphism, là các dạng. Tính đa hình là khả năng sử dụng các đối tượng khác nhau theo một cách chung. Ví dụ: khi bạn kết nối loa Bluetooth với điện thoại di động, điện thoại chỉ cần biết có một thiết bị có thể phát âm thanh bằng Bluetooth. Tuy nhiên, có nhiều loa Bluetooth để bạn chọn và điện thoại không cần phải biết cụ thể cách làm việc với từng loa.

Cuối cùng, bạn sẽ tìm hiểu về các lớp uỷ quyền thuộc tính. Đây là những lớp cung cấp mã có thể sử dụng lại để quản lý các giá trị thuộc tính bằng một cú pháp ngắn gọn. Trong lớp học lập trình này, bạn sẽ học những khái niệm này khi xây dựng cấu trúc lớp cho ứng dụng nhà thông minh.

Điều kiện tiên quyết

  • Cách mở, chỉnh sửa và chạy mã trong Kotlin Playground.
  • Kiến thức cơ bản về lập trình Kotlin, bao gồm các biến, hàm và hàm

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    7 và

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    8

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

  • Tổng quan về OOP.
  • Định nghĩa về lớp.
  • Cách xác định lớp bằng hàm khởi tạo, hàm và thuộc tính.
  • Cách tạo thực thể cho một đối tượng.
  • Định nghĩa về tính kế thừa.
  • Sự khác biệt giữa mối quan hệ IS-A và HAS-A.
  • Cách ghi đè thuộc tính và hàm.
  • Công cụ sửa đổi chế độ hiển thị là gì.
  • Ủy quyền là gì và cách sử dụng ủy quyền

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    9.

Sản phẩm bạn sẽ tạo ra

  • Cấu trúc lớp trong nhà thông minh.
  • Lớp đại diện cho các thiết bị thông minh, chẳng hạn như TV thông minh và đèn thông minh.

Bạn cần có

  • Một chiếc máy tính có kết nối Internet và trình duyệt web

2. Xác định một lớp

Khi xác định một lớp, bạn sẽ chỉ định các thuộc tính và phương thức tất cả đối tượng của lớp đó phải có.

Định nghĩa lớp bắt đầu bằng từ khoá

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

0, theo sau là tên và cặp dấu ngoặc nhọn. Phần cú pháp trước dấu ngoặc nhọn cũng được gọi là tiêu đề lớp. Trong dấu ngoặc nhọn, bạn có thể chỉ định các thuộc tính và hàm cho lớp. Bạn sẽ sớm tìm hiểu về các thuộc tính và hàm. Bạn có thể xem cú pháp của định nghĩa lớp trong sơ đồ này:

Dưới đây là những quy ước đặt tên được đề xuất cho một lớp:

  • Bạn có thể chọn bất kỳ tên lớp nào mình muốn, nhưng không được dùng từ khóa Kotlin làm tên lớp, chẳng hạn như từ khóa

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    1.
  • Tên lớp được viết bằng PascalCase, vì vậy, mỗi từ bắt đầu bằng một chữ cái viết hoa và không có dấu cách giữa các từ. Ví dụ: trong SmartDevice, chữ cái đầu tiên của mỗi từ được viết hoa và không có dấu cách giữa các từ.

Một lớp bao gồm 3 phần chính:

  • Properties [Thuộc tính]. Các biến chỉ định thuộc tính của đối tượng của lớp.
  • Phương thức. Các hàm chứa hành vi và hành động của lớp.
  • Hàm khởi tạo Một hàm thành viên đặc biệt tạo các thực thể của lớp trong toàn bộ chương trình định nghĩa hàm này.

Đây không phải là lần đầu tiên bạn làm việc với các lớp. Trong các lớp học lập trình trước đây, bạn đã tìm hiểu về các loại dữ liệu, chẳng hạn như loại dữ liệu

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

2,

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

3,

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

4 và

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

5. Các loại dữ liệu này được xác định là lớp trong Kotlin. Khi xác định một biến như trong đoạn mã dưới đây, bạn sẽ tạo một đối tượng của lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

2. Lớp này được tạo thực thể bằng giá trị

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

7:

val number: Int = 1

Xác định một lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8:

  1. Trong Kotlin Playground, hãy thay nội dung bằng một hàm

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    8 trống:

fun main[] {
}

  1. Trên dòng trước hàm

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    8, hãy xác định lớp

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8 có nội dung bao gồm một nhận xét

    fun main[] { }

    02

    fun main[] { }

    03

    fun main[] { }

    04:

class SmartDevice {
    // empty body
}
fun main[] {
}

3. Tạo một thực thể của lớp

Như bạn đã biết, lớp là bản thiết kế của một đối tượng. Thời gian chạy Kotlin sử dụng lớp hoặc bản thiết kế để tạo một đối tượng thuộc loại cụ thể đó. Với lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8, bạn sẽ có bản thiết kế của một thiết bị thông minh. Để có thiết bị thông minh thực tế trong chương trình, bạn cần tạo một thực thể đối tượng

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8. Cú pháp tạo thực thể bắt đầu bằng tên lớp, theo sau là một cặp dấu ngoặc đơn như có thể thấy trong sơ đồ dưới đây:

Để sử dụng một đối tượng, bạn sẽ tạo đối tượng và gán đối tượng đó cho một biến, tương tự như cách bạn xác định một biến. Bạn dùng từ khoá

fun main[] {
}

07 để tạo biến không thể thay đổi và từ khoá

fun main[] {
}

08 cho biến có thể thay đổi. Từ khoá

fun main[] {
}

07 hoặc

fun main[] {
}

08 theo sau là tên của biến, sau đó là một toán tử gán

fun main[] {
}

11 rồi đến thực thể của đối tượng lớp. Bạn có thể xem cú pháp trong sơ đồ này:

Tạo thực thể lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8 dưới dạng một đối tượng:

  • Trong hàm

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    8, hãy dùng từ khóa

    fun main[] { }

    07 để tạo một biến có tên

    fun main[] { }

    15 và khởi tạo biến đó dưới dạng một bản sao của lớp

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8:

fun main[] {
    val smartTvDevice = SmartDevice[]
}

4. Xác định các phương thức của lớp

Trong Bài 1, bạn đã được học về:

  • Định nghĩa về hàm sử dụng từ khoá

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    1 theo sau là cặp dấu ngoặc đơn và dấu ngoặc nhọn. Dấu ngoặc nhọn chứa mã, là hướng dẫn cần thiết để thực thi một tác vụ.
  • Việc gọi một hàm có thể khiến mã chứa trong hàm đó thực thi.

Các thao tác lớp có thể thực hiện được xác định là các hàm trong lớp. Ví dụ: hãy tưởng tượng bạn sở hữu một thiết bị thông minh, TV thông minh hoặc đèn thông minh và bạn có thể bật/tắt thiết bị đó bằng điện thoại di động. Thiết bị thông minh này được chuyển thành lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8 trong quá trình lập trình. Thao tác bật/tắt thiết bị này sẽ được biểu thị bằng hàm

fun main[] {
}

19 và hàm

fun main[] {
}

20, cho phép kích hoạt hành vi bật/tắt đó.

Cú pháp để xác định một hàm trong lớp giống hệt với cú pháp bạn đã học trước đó. Điểm khác biệt duy nhất là hàm được đặt trong phần nội dung của lớp. Khi bạn xác định một hàm trong phần nội dung lớp, hàm đó được gọi là hàm thành phần hoặc phương thức và đại diện cho hành vi của lớp. Trong phần còn lại của lớp học lập trình này, các hàm được gọi là phương thức bất cứ khi nào chúng xuất hiện trong phần nội dung của một lớp.

Xác định phương thức

fun main[] {
}

19 và

fun main[] {
}

20 trong lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8:

  1. Trong phần nội dung của lớp

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8, hãy xác định một phương thức

    fun main[] { }

    19 có phần nội dung trống:

class SmartDevice {
    fun turnOn[] {
    }
}

  1. Trong phần nội dung của phương thức

    fun main[] { }

    19, hãy thêm một câu lệnh

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    7 rồi truyền câu lệnh đó thành một chuỗi

    fun main[] { }

    28

    fun main[] { }

    29

    fun main[] { }

    30

    fun main[] { }

    31

    fun main[] { }

    32:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

  1. Sau phương thức

    fun main[] { }

    19, hãy thêm một phương thức

    fun main[] { }

    20 để in chuỗi

    fun main[] { }

    28

    fun main[] { }

    29

    fun main[] { }

    30

    fun main[] { }

    31

    fun main[] { }

    39:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
    fun turnOff[] {
        println["Smart device is turned off."]
    }
}

Gọi một phương thức trên một đối tượng

Cho đến phần này, bạn đã xác định một lớp đóng vai trò là bản thiết kế cho một thiết bị thông minh, tạo một thực thể của lớp và gán thực thể đó cho một biến. Giờ đây, bạn có thể dùng phương thức của lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8 để bật và tắt thiết bị.

Lệnh gọi một phương thức trong một lớp tương tự như cách bạn gọi các hàm khác từ hàm

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
}

8 trong lớp học lập trình trước đó. Ví dụ: nếu cần gọi phương thức

fun main[] {
}

20 từ phương thức

fun main[] {
}

19, bạn có thể viết nội dung tương tự như đoạn mã này:

class SmartDevice {
    fun turnOn[] {
        // A valid use case to call the turnOff[] method could be to turn off the TV when available power doesn't meet the requirement.
        turnOff[]
        ...
    }
    ...
}

Để gọi một phương thức lớp bên ngoài lớp, hãy bắt đầu bằng đối tượng lớp theo sau là toán tử

fun main[] {
}

44, tên hàm và một cặp dấu ngoặc đơn. Nếu có thể, dấu ngoặc đơn có chứa các đối số mà phương thức yêu cầu. Bạn có thể xem cú pháp trong sơ đồ này:

Gọi phương thức

fun main[] {
}

19 và

fun main[] {
}

20 trên đối tượng:

  1. Trong hàm

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    8 trên dòng ở sau biến

    fun main[] { }

    15, hãy gọi phương thức

    fun main[] { }

    19:

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
}

  1. Trên dòng ở sau phương thức

    fun main[] { }

    19, hãy gọi phương thức

    fun main[] { }

    20:

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

  1. Chạy mã.

Kết quả sẽ như sau:

fun main[] {
}

0

5. Xác định các thuộc tính của lớp

Trong Bài 1, bạn đã học về các biến, là các vùng chứa cho một phần dữ liệu. Bạn đã tìm hiểu cách tạo một biến chỉ có thể đọc bằng từ khoá

fun main[] {
}

07 và biến có thể thay đổi bằng từ khoá

fun main[] {
}

08.

Trong khi phương thức xác định các thao tác một lớp có thể thực hiện, thì các thuộc tính này xác định các đặc điểm hoặc thuộc tính dữ liệu của lớp. Ví dụ: một thiết bị thông minh có các thuộc tính sau:

  • Tên Tên thiết bị.
  • Loại thiết bị. Loại thiết bị thông minh, chẳng hạn như giải trí, tiện ích hoặc nấu ăn.
  • Trạng thái thiết bị. Cho dù thiết bị đang bật, tắt, trực tuyến hay ngoại tuyến. Thiết bị được coi là trực tuyến khi kết nối với Internet. Nếu không, nó sẽ được xem là ngoại tuyến.

Về cơ bản, thuộc tính là các biến được xác định trong phần nội dung lớp thay vì phần nội dung hàm. Điều này có nghĩa là cú pháp để xác định thuộc tính và biến giống hệt nhau. Bạn xác định một thuộc tính không thể thay đổi bằng từ khoá

fun main[] {
}

07 và thuộc tính có thể thay đổi bằng từ khoá

fun main[] {
}

08.

Triển khai các đặc điểm nói trên dưới dạng thuộc tính của lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8:

  1. Trên dòng trước phương thức

    fun main[] { }

    19, hãy xác định thuộc tính

    fun main[] { }

    58 và gán thuộc tính này cho một chuỗi

    fun main[] { }

    59

    fun main[] { }

    60:

fun main[] {
}

1

  1. Trên dòng sau thuộc tính

    fun main[] { }

    58, hãy xác định thuộc tính

    fun main[] { }

    62 và chỉ định thuộc tính đó cho chuỗi

    fun main[] { }

    63, sau đó xác định thuộc tính

    fun main[] { }

    64 và chỉ định thuộc tính đó cho chuỗi

    fun main[] { }

    65:

fun main[] {
}

2

  1. Trên dòng sau biến

    fun main[] { }

    15, hãy gọi hàm

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    7 rồi truyền hàm này vào một chuỗi

    fun main[] { }

    68

    fun main[] { }

    58

    fun main[] { }

    70

    fun main[] { }

    71:

fun main[] {
}

3

  1. Chạy mã.

Kết quả sẽ như sau:

fun main[] {
}

4

Hàm getter và setter trong các thuộc tính

Thuộc tính có thể làm được nhiều việc hơn một biến. Ví dụ: giả sử bạn tạo một cấu trúc lớp để đại diện cho một TV thông minh. Một trong những hành động phổ biến bạn thực hiện là tăng và giảm âm lượng. Để thể hiện hành động này trong lập trình, bạn có thể tạo một thuộc tính có tên là

fun main[] {
}

72. Thuộc tính này giữ mức âm lượng hiện tại được đặt trên loa TV, nhưng có phạm vi giá trị cho âm lượng. Âm lượng tối thiểu có thể đặt là 0 và tối đa là 100. Để đảm bảo thuộc tính

fun main[] {
}

72 không bao giờ vượt quá 100 hoặc thấp hơn 0, bạn có thể viết một hàm setter. Khi cập nhật giá trị của thuộc tính, bạn cần kiểm tra xem giá trị đó có nằm trong khoảng từ 0 đến 100 hay không. Một ví dụ khác, hãy tưởng tượng có một yêu cầu để đảm bảo tên luôn phải viết hoa. Bạn có thể triển khai hàm getter để chuyển đổi thuộc tính

fun main[] {
}

58 thành chữ viết hoa.

Trước khi tìm hiểu sâu hơn về cách triển khai các thuộc tính này, bạn cần hiểu rõ cú pháp để khai báo thuộc tính. Cú pháp đầy đủ để xác định thuộc tính có thể thay đổi bắt đầu bằng định nghĩa biến, theo sau là các hàm

fun main[] {
}

75 và

fun main[] {
}

76 [không bắt buộc]. Bạn có thể xem cú pháp trong sơ đồ này:

Khi bạn không xác định hàm getter và setter cho một thuộc tính, trình biên dịch Kotlin sẽ tạo các hàm đó trong nội bộ. Ví dụ: nếu bạn sử dụng từ khoá

fun main[] {
}

08 để xác định một thuộc tính

fun main[] {
}

72 và gán một giá trị

fun main[] {
}

79 cho thuộc tính đó, trình biên dịch sẽ tự động tạo các hàm getter và setter như có thể thấy trong đoạn mã dưới đây:

fun main[] {
}

5

Bạn sẽ không thấy những dòng này trong mã vì trình biên dịch đã thêm chúng vào nền.

Cú pháp đầy đủ cho thuộc tính không thể thay đổi có hai điểm khác biệt:

  • Nó bắt đầu với từ khóa

    fun main[] { }

    07.
  • Các biến của

    fun main[] { }

    07 là các loại chỉ được đọc, do đó, chúng không có hàm

    fun main[] { }

    76.

Thuộc tính Kotlin sử dụng trường sao lưu để lưu giữ giá trị trong bộ nhớ. Trường sao lưu về cơ bản là một biến lớp được xác định nội bộ bên trong các thuộc tính. Trường sao lưu nằm trong phạm vi một thuộc tính, có nghĩa là bạn chỉ có thể truy cập vào trường đó thông qua các hàm thuộc tính

fun main[] {
}

75 hoặc

fun main[] {
}

76.

Để đọc giá trị thuộc tính trong hàm

fun main[] {
}

75 hoặc cập nhật giá trị trong hàm

fun main[] {
}

76, bạn cần sử dụng trường sao lưu của thuộc tính. Tệp này được trình biên dịch Kotlin tạo tự động và được tham chiếu bằng giá trị nhận dạng

fun main[] {
}

87.

Ví dụ: khi muốn cập nhật giá trị của thuộc tính trong hàm

fun main[] {
}

76, bạn sử dụng tham số của hàm

fun main[] {
}

76 [còn được gọi là tham số

fun main[] {
}

  1. và gán giá trị đó cho

fun main[] {
}

87 biến như bạn có thể thấy trong đoạn mã này:

fun main[] {
}

6

Ví dụ: để đảm bảo giá trị được gán cho thuộc tính

fun main[] {
}

72 nằm trong khoảng từ 0 đến 100, bạn có thể triển khai hàm setter như có thể thấy trong đoạn mã dưới đây:

fun main[] {
}

7

Hàm

fun main[] {
}

76 kiểm tra xem giá trị

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

2 có nằm trong phạm vi từ 0 đến 100 hay không bằng cách dùng từ khoá

fun main[] {
}

95 theo sau là phạm vi giá trị. Nếu giá trị nằm trong phạm vi dự kiến, thì giá trị

fun main[] {
}

87 sẽ được cập nhật. Nếu không, giá trị của thuộc tính sẽ không thay đổi.

Bạn sẽ thêm thuộc tính này vào một lớp trong phần Triển khai mối quan hệ giữa các lớp của lớp học lập trình này, vì vậy, hiện tại bạn chưa cần phải thêm hàm setter vào mã.

6. Xác định hàm khởi tạo

Mục đích chính của hàm khởi tạo là chỉ định cách các đối tượng của lớp được tạo. Nói cách khác, hàm khởi tạo sẽ tạo một đối tượng và khiến đối tượng đó sẵn sàng để sử dụng. Bạn làm việc này khi tạo thực thể cho đối tượng. Mã bên trong hàm khởi tạo thực thi khi đối tượng của lớp được tạo thực thể. Bạn có thể xác định một hàm khởi tạo có hoặc không có tham số.

Hàm khởi tạo mặc định

Hàm khởi tạo mặc định là hàm khởi tạo không có tham số. Bạn có thể xác định một hàm khởi tạo mặc định như trong đoạn mã này:

fun main[] {
}

8

Kotlin luôn hướng đến sự súc tích, vì vậy bạn có thể xoá từ khoá

fun main[] {
}

97 nếu không có chú thích hoặc công cụ sửa đổi chế độ hiển thị [bạn sẽ sớm được tìm hiểu về nó] trên hàm khởi tạo. Bạn cũng có thể xoá dấu ngoặc đơn nếu hàm khởi tạo không có tham số như minh hoạ trong đoạn mã dưới đây:

fun main[] {
}

9

Trình biên dịch Kotlin sẽ tự động tạo hàm khởi tạo mặc định. Bạn sẽ không thấy hàm khởi tạo mặc định được tạo tự động trong mã vì hàm đó đã được trình biên dịch thêm vào trong nền.

Xác định một hàm khởi tạo có tham số

Trong lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8, các thuộc tính

fun main[] {
}

58 và

fun main[] {
}

62 là không thể thay đổi. Bạn cần đảm bảo tất cả các thực thể của lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8 đều khởi tạo các thuộc tính

fun main[] {
}

58 và

fun main[] {
}

62. Bằng cách triển khai hiện tại, các giá trị của thuộc tính

fun main[] {
}

58 và

fun main[] {
}

62 đã được mã hóa cứng. Điều này có nghĩa là tất cả thiết bị thông minh được đặt tên bằng chuỗi

fun main[] {
}

59

fun main[] {
}

60 và được phân loại bằng chuỗi

fun main[] {
}

63.

Để duy trì tính bất biến nhưng tránh các giá trị được mã hoá cứng, hãy dùng một hàm khởi tạo có tham số để tạo các giá trị đó:

  • Trong lớp

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8, hãy di chuyển các thuộc tính

    fun main[] { }

    58 và

    fun main[] { }

    62 sang hàm khởi tạo không phải chỉ định giá trị mặc định:

class SmartDevice {
    // empty body
}
fun main[] {
}

0

Hàm khởi tạo hiện chấp nhận các tham số để thiết lập thuộc tính, vì vậy, cách tạo thực thể của một đối tượng cho lớp đó cũng sẽ thay đổi. Bạn có thể xem cú pháp đầy đủ để tạo thực thể cho một đối tượng trong sơ đồ này:

Dưới đây là nội dung biểu thị dòng mã:

class SmartDevice {
    // empty body
}
fun main[] {
}

1

Cả hai đối số cho hàm khởi tạo đều là chuỗi. Nó không rõ ràng về giá trị cần chỉ định cho tham số. Để khắc phục lỗi này, tương tự như cách bạn chuyển các đối số của hàm, bạn có thể tạo một hàm khởi tạo có đối số được đặt tên như minh hoạ trong đoạn mã dưới đây:

class SmartDevice {
    // empty body
}
fun main[] {
}

2

Có hai loại hàm khởi tạo chính trong Kotlin:

  • Hàm khởi tạo chính. Một lớp chỉ có thể có một hàm khởi tạo chính, được xác định là một phần của tiêu đề lớp. Một hàm khởi tạo chính có thể là một hàm khởi tạo mặc định hoặc có tham số. Hàm khởi tạo chính không có nội dung. Điều đó có nghĩa là nó không được chứa bất kỳ mã nào.
  • Hàm khởi tạo phụ. Một lớp có thể có nhiều hàm khởi tạo phụ. Bạn có thể xác định hàm khởi tạo phụ có hoặc không có tham số. Hàm khởi tạo phụ có thể khởi tạo lớp và có một phần nội dung có thể chứa logic khởi tạo. Nếu lớp có một hàm khởi tạo chính, mỗi hàm khởi tạo phụ đều phải tạo hàm khởi tạo chính.

Bạn có thể dùng hàm khởi tạo chính để tạo các thuộc tính trong tiêu đề lớp. Các đối số được chuyển đến hàm khởi tạo được gán cho các thuộc tính. Cú pháp để xác định một hàm khởi tạo chính bắt đầu bằng tên lớp, theo sau là từ khoá

fun main[] {
}

97 và một cặp dấu ngoặc đơn. Dấu ngoặc đơn chứa các tham số cho hàm khởi tạo chính. Nếu có nhiều hơn một tham số, dấu phẩy sẽ phân tách các định nghĩa tham số. Bạn có thể xem cú pháp đầy đủ để xác định một hàm khởi tạo chính trong sơ đồ này:

Hàm khởi tạo phụ nằm trong phần nội dung của lớp và cú pháp của hàm này bao gồm 3 phần:

  • Khai báo hàm khởi tạo phụ. Việc xác định hàm khởi tạo phụ bắt đầu bằng từ khoá

    fun main[] { }

    97 theo sau là dấu ngoặc đơn. Nếu thích hợp, dấu ngoặc đơn chứa các tham số mà hàm khởi tạo phụ yêu cầu.
  • Khởi tạo hàm khởi tạo chính. Khởi tạo bằng dấu hai chấm, theo sau là từ khoá

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    14 và một cặp dấu ngoặc đơn. Nếu thích hợp, dấu ngoặc đơn sẽ chứa các tham số hàm khởi tạo chính yêu cầu.
  • Nội dung hàm khởi tạo phụ. Khởi tạo hàm khởi tạo chính, theo sau là một cặp dấu ngoặc nhọn, chứa phần nội dung của hàm khởi tạo phụ.

Bạn có thể xem cú pháp trong sơ đồ này:

Ví dụ: giả sử bạn muốn tích hợp API do một nhà cung cấp thiết bị thông minh phát triển. Tuy nhiên, API sẽ trả về mã trạng thái của loại

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

2 để cho biết trạng thái thiết bị ban đầu. API trả về một giá trị

class SmartDevice {
    // empty body
}
fun main[] {
}

16 nếu thiết bị ngoại tuyến và một giá trị

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

7 nếu thiết bị đó trực tuyến. Đối với bất kỳ giá trị số nguyên nào khác, trạng thái được coi là không xác định. Bạn có thể tạo một hàm khởi tạo phụ trong lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8 để chuyển đổi tham số

class SmartDevice {
    // empty body
}
fun main[] {
}

19 này thành giá trị biểu diễn dạng chuỗi như có thể thấy trong đoạn mã dưới đây:

class SmartDevice {
    // empty body
}
fun main[] {
}

3

7. Triển khai mối quan hệ giữa các lớp

Tính kế thừa cho phép bạn tạo một lớp dựa trên đặc điểm và hành vi của một lớp khác. Đây là một cơ chế hiệu quả giúp bạn viết mã có thể sử dụng lại và thiết lập mối quan hệ giữa các lớp.

Ví dụ: có nhiều thiết bị thông minh trên thị trường, chẳng hạn như TV thông minh, đèn thông minh và công tắc thông minh. Khi bạn biểu diễn các thiết bị thông minh trong lập trình, chúng sẽ dùng chung một số thuộc tính như tên, danh mục và trạng thái. Chúng cũng có các hành vi phổ biến, chẳng hạn như khả năng bật và tắt những tuỳ chọn đó.

Tuy nhiên, cách bật hoặc tắt từng thiết bị thông minh sẽ khác nhau. Ví dụ: để bật TV, bạn có thể phải bật màn hình, sau đó thiết lập mức âm lượng và kênh đã mở lần gần nhất. Mặt khác, để bật đèn, bạn có thể chỉ cần tăng hoặc giảm độ sáng.

Ngoài ra, mỗi thiết bị thông minh có nhiều chức năng và thao tác thực hiện hơn. Ví dụ: đối với TV, bạn có thể điều chỉnh âm lượng và thay đổi kênh. Với đèn, bạn có thể điều chỉnh độ sáng hoặc màu sắc.

Tóm lại, tất cả các thiết bị thông minh đều có các tính năng khác nhau, nhưng có chung một số đặc điểm. Bạn có thể sao chép các đặc điểm chung này tới từng lớp thiết bị thông minh hoặc làm cho mã có thể tái sử dụng với tính kế thừa.

Để làm việc này, bạn cần tạo một lớp mẹ

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8 và xác định các thuộc tính cũng như hành vi phổ biến này. Sau đó, bạn có thể tạo các lớp con, chẳng hạn như lớp

class SmartDevice {
    // empty body
}
fun main[] {
}

21 và

class SmartDevice {
    // empty body
}
fun main[] {
}

22. Các lớp này kế thừa các thuộc tính của lớp cha.

Trong các ngôn ngữ lập trình, chúng ta nói lớp

class SmartDevice {
    // empty body
}
fun main[] {
}

21 và

class SmartDevice {
    // empty body
}
fun main[] {
}

22 mở rộng lớp mẹ

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8. Lớp mẹ còn được gọi là lớp cấp cao và lớp con là lớp phụ. Bạn có thể thấy mối quan hệ giữa chúng trong sơ đồ này:

Tuy nhiên, trong Kotlin, theo mặc định, tất cả các lớp đều là cuối cùng, nghĩa là bạn không thể mở rộng chúng, vì vậy bạn phải xác định mối quan hệ giữa các lớp.

Xác định mối quan hệ giữa lớp cấp cao

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8 và các lớp con của chúng:

  1. Trong lớp cấp cao

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8, hãy thêm từ khoá

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    28 trước từ khoá

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    0 để có thể mở rộng từ khoá này:

class SmartDevice {
    // empty body
}
fun main[] {
}

4

Từ khoá

class SmartDevice {
    // empty body
}
fun main[] {
}

28 thông báo cho trình biên dịch rằng lớp này có thể mở rộng. Nhờ đó, vào lúc này lớp khác sẽ có thể mở rộng lớp này.

Cú pháp để tạo lớp con bắt đầu bằng việc tạo tiêu đề lớp như bạn đã làm từ trước đến nay. Sau dấu ngoặc đơn đóng của hàm khởi tạo là dấu cách, dấu hai chấm, dấu cách khác, tên lớp cấp cao và một cặp dấu ngoặc đơn. Nếu cần, dấu ngoặc đơn sẽ bao gồm các tham số mà hàm khởi tạo lớp cấp cao yêu cầu. Bạn có thể xem cú pháp trong sơ đồ này:

  1. Tạo lớp con

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21 mở rộng lớp cấp cao

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8:

class SmartDevice {
    // empty body
}
fun main[] {
}

5

Việc xác định

fun main[] {
}

97 cho

class SmartDevice {
    // empty body
}
fun main[] {
}

21 không chỉ định xem các thuộc tính này có thể thay đổi hay không thể thay đổi. Điều này có nghĩa là tham số

class SmartDevice {
    // empty body
}
fun main[] {
}

35 và

class SmartDevice {
    // empty body
}
fun main[] {
}

36 chỉ là tham số

fun main[] {
}

97 hơn là thuộc tính lớp. Bạn sẽ không thể dùng chúng trong lớp này, chỉ cần chuyển các lớp đó đến hàm khởi tạo lớp cấp cao.

  1. Trong phần nội dung của lớp con

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21, hãy thêm thuộc tính

    fun main[] { }

    72 bạn đã tạo khi được học về các hàm getter và setter:

class SmartDevice {
    // empty body
}
fun main[] {
}

6

  1. Xác định một thuộc tính

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    40 được chỉ định cho giá trị

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    7 bằng một hàm setter chỉ định một phạm vi

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    42:

class SmartDevice {
    // empty body
}
fun main[] {
}

7

  1. Xác định phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    43 tăng âm lượng và in chuỗi

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    44

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    45

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    46

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    47

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    48:

class SmartDevice {
    // empty body
}
fun main[] {
}

8

  1. Thêm phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    49 để tăng số lượng kênh và in chuỗi

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    50

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    51

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    46

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    47

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    54:

class SmartDevice {
    // empty body
}
fun main[] {
}

9

  1. Trên dòng sau lớp con

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21, hãy xác định lớp con

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22 mở rộng lớp cấp cao

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8:

fun main[] {
    val smartTvDevice = SmartDevice[]
}

0

  1. Trong phần nội dung lớp con

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22, hãy xác định một thuộc tính

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    59 được gán cho giá trị

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    16 bằng một hàm setter chỉ định một phạm vi

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    61:

fun main[] {
    val smartTvDevice = SmartDevice[]
}

1

  1. Xác định phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    62 tăng độ sáng của đèn và in chuỗi

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    63

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    46

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    47

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    66:

fun main[] {
    val smartTvDevice = SmartDevice[]
}

2

Mối quan hệ giữa các lớp

Khi sử dụng tính kế thừa, bạn thiết lập mối quan hệ giữa hai lớp trong mối quan hệ IS-A. Đối tượng cũng là một thực thể của lớp, từ đó đối tượng này kế thừa. Trong mối quan hệ HAS-A, một đối tượng có thể sở hữu một thực thể của lớp khác mà không thực sự là thực thể của lớp đó. Bạn có thể thấy phần biểu thị cấp cao về các mối quan hệ trong sơ đồ dưới đây:

Mối quan hệ IS-A

Khi bạn chỉ định mối quan hệ IS-A giữa lớp cấp cao

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8 và lớp con

class SmartDevice {
    // empty body
}
fun main[] {
}

21, điều đó có nghĩa là lớp con

class SmartDevice {
    // empty body
}
fun main[] {
}

21 có thể làm bất cứ điều gì mà lớp cấp cao

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8 làm được. Mối quan hệ này là một chiều, vì vậy mỗi TV thông minh là một thiết bị thông minh nhưng mỗi thiết bị thông minh không hẳn đều là TV thông minh. Mã biểu thị cho mối quan hệ IS-A được minh hoạ trong đoạn mã dưới đây:

fun main[] {
    val smartTvDevice = SmartDevice[]
}

3

Không sử dụng tính kế thừa chỉ để đạt được tính tái sử dụng mã. Trước khi bạn quyết định, hãy kiểm tra xem hai lớp có liên quan với nhau hay không. Nếu chúng có thể hiện một số mối quan hệ, hãy kiểm tra xem chúng có thực sự đủ điều kiện để thiết lập mối quan hệ IS-A hay không. Hãy tự hỏi: "Lớp con có phải là lớp cấp cao không?". Ví dụ: Android là một hệ điều hành.

Mối quan hệ HAS-A

Mối quan hệ HAS-A là một cách khác để chỉ định mối quan hệ giữa hai lớp. Ví dụ: bạn có thể đang sử dụng TV thông minh tại nhà của mình. Trong trường hợp này, có mối quan hệ giữa TV thông minh và nhà bạn. Nhà này có chứa một thiết bị thông minh, hoặc nói cách khác là nhà có mộtthiết bị thông minh. Mối quan hệ HAS-A giữa hai lớp cũng được gọi là sự kết hợp.

Cho đến nay, bạn đã tạo được một vài thiết bị thông minh. Bây giờ, bạn sẽ tạo lớp

class SmartDevice {
    // empty body
}
fun main[] {
}

71, chứa các thiết bị thông minh. Lớp

class SmartDevice {
    // empty body
}
fun main[] {
}

71 cho phép bạn tương tác với các thiết bị thông minh.

Sử dụng mối quan hệ HAS-A để xác định lớp

class SmartDevice {
    // empty body
}
fun main[] {
}

71:

  1. Ở giữa lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22 và hàm

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    8, hãy xác định một lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    71:

fun main[] {
    val smartTvDevice = SmartDevice[]
}

4

  1. Trong hàm khởi tạo lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    71, hãy dùng từ khóa

    fun main[] { }

    07 để tạo thuộc tính

    fun main[] { }

    15 thuộc loại

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21:

fun main[] {
    val smartTvDevice = SmartDevice[]
}

5

  1. Trong phần nội dung của lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    71, hãy xác định một phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    82 để gọi phương thức

    fun main[] { }

    19 trên thuộc tính

    fun main[] { }

    15:

fun main[] {
    val smartTvDevice = SmartDevice[]
}

6

  1. Trên dòng sau phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    82, hãy xác định phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    86 để gọi phương thức

    fun main[] { }

    20 trên thuộc tính

    fun main[] { }

    15:

fun main[] {
    val smartTvDevice = SmartDevice[]
}

7

  1. Trên dòng sau phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    86, hãy xác định phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    90 để gọi phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    43 trên thuộc tính

    fun main[] { }

    15, sau đó xác định phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    93 để gọi phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    49 trên thuộc tính

    fun main[] { }

    15:

fun main[] {
    val smartTvDevice = SmartDevice[]
}

8

  1. Trong hàm khởi tạo lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    71, di chuyển tham số thuộc tính

    fun main[] { }

    15 sang dòng riêng, theo sau là dấu phẩy:

fun main[] {
    val smartTvDevice = SmartDevice[]
}

9

  1. Trên dòng sau thuộc tính

    fun main[] { }

    15, dùng từ khóa

    fun main[] { }

    07 để xác định thuộc tính

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    00 thuộc loại

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22:

class SmartDevice {
    fun turnOn[] {
    }
}

0

  1. Trong

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    71 nội dung, xác định phương thức

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    03 để gọi phương thức

    fun main[] { }

    19 trên đối tượng

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    00 và một đối tượng

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    06 để gọi phương thức

    fun main[] { }

    20 trên đối tượng

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    00:

class SmartDevice {
    fun turnOn[] {
    }
}

1

  1. Trên dòng sau phương thức

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    06, hãy xác định phương thức

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    10 để gọi phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    62 trên thuộc tính

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    00:

class SmartDevice {
    fun turnOn[] {
    }
}

2

  1. Trên dòng sau phương thức

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    10, hãy xác định phương thức

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    14 để gọi phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    86 và

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    06:.

class SmartDevice {
    fun turnOn[] {
    }
}

3

Ghi đè phương thức của lớp cấp cao từ các lớp con

Như đã thảo luận trước đó, mặc dù chức năng bật và tắt được tất cả các thiết bị thông minh hỗ trợ, nhưng cách thực hiện chức năng này lại khác nhau. Để cung cấp hành vi dành riêng cho thiết bị này, bạn cần ghi đè phương thức

fun main[] {
}

19 và

fun main[] {
}

20 được xác định trong lớp cấp cao. Để ghi đè nghĩa là chặn hành động, thường là để kiểm soát thủ công. Khi bạn ghi đè một phương thức, phương thức trong lớp con sẽ làm gián đoạn quá trình thực thi phương thức được xác định trong lớp cấp cao và cung cấp phương thức thực thi của chính nó.

Ghi đè lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8 phương thức

fun main[] {
}

19 và

fun main[] {
}

20:

  1. Trong phần nội dung của lớp cấp cao

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8 trước từ khoá

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    1 của mỗi phương thức, hãy thêm từ khoá

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    28:

class SmartDevice {
    fun turnOn[] {
    }
}

4

  1. Trong phần nội dung của lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22, hãy xác định một phương thức

    fun main[] { }

    19 có phần nội dung trống:

class SmartDevice {
    fun turnOn[] {
    }
}

5

  1. Trong phần nội dung của phương thức

    fun main[] { }

    19, thiết lập thuộc tính

    fun main[] { }

    64 thành chuỗi "

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    29", thiết lập thuộc tính

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    59 thành một giá trị

    fun main[] { }

    79, rồi thêm câu lệnh

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    7 sau đó truyền vào câu lệnh đó chuỗi

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    33

    fun main[] { }

    31

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    35

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    36

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    37

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    38

    fun main[] { }

    30

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    66:

class SmartDevice {
    fun turnOn[] {
    }
}

6

  1. Trong phần nội dung của lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22, hãy xác định một phương thức

    fun main[] { }

    20 có phần nội dung trống:

class SmartDevice {
    fun turnOn[] {
    }
}

7

  1. Trong phần nội dung của phương thức

    fun main[] { }

    20, thiết lập thuộc tính

    fun main[] { }

    64 thành chuỗi "

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    45", thiết lập thuộc tính

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    59 thành một giá trị

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    16 rồi thêm câu lệnh

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    7 sau đó truyền vào câu lệnh đó chuỗi

    fun main[] { }

    28

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    50

    fun main[] { }

    31

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    52:

class SmartDevice {
    fun turnOn[] {
    }
}

8

  1. Trong lớp con

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22 trước từ khoá

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    1 của phương thức

    fun main[] { }

    19 và

    fun main[] { }

    20, hãy thêm từ khoá

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    57:

class SmartDevice {
    fun turnOn[] {
    }
}

9

Từ khoá

fun main[] {
    val smartTvDevice = SmartDevice[]
}

57 thông báo cho Kotlin trong thời gian chạy để thực thi mã có trong phương thức đã xác định trong lớp con.

  1. Trong phần nội dung của lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21, hãy xác định một phương thức

    fun main[] { }

    19 có phần nội dung trống:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

0

  1. Trong phần nội dung của phương thức

    fun main[] { }

    19, hãy thiết lập thuộc tính

    fun main[] { }

    64 thành chuỗi "

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    29" rồi thêm một câu lệnh

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    7, sau đó truyền vào đó chuỗi

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    65:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

1

  1. Trong phần nội dung của lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21 sau phương thức

    fun main[] { }

    19, hãy xác định phương thức

    fun main[] { }

    20 có phần nội dung trống:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

2

  1. Trong phần nội dung của phương thức

    fun main[] { }

    20, hãy thiết lập thuộc tính

    fun main[] { }

    64 thành chuỗi "

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    45" rồi thêm câu lệnh

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    7, sau đó truyền vào đó chuỗi

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    33

    fun main[] { }

    31

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    52:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

3

  1. Trong lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21 trước từ khoá

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    1 của phương thức

    fun main[] { }

    19 và

    fun main[] { }

    20, hãy thêm từ khoá

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    57:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

4

  1. Trong hàm

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    8, hãy dùng từ khoá

    fun main[] { }

    08 để xác định biến

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    83 thuộc loại

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8 sẽ tạo thực thể cho đối tượng

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21 để lấy đối số

    fun main[] { }

    59

    fun main[] { }

    60 và đối số

    fun main[] { }

    63:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

5

  1. Trên dòng sau biến

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    83, gọi phương thức

    fun main[] { }

    19 trên đối tượng

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    83:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

6

  1. Chạy mã.

Kết quả sẽ như sau:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

7

  1. Trên dòng sau khi gọi phương thức

    fun main[] { }

    19, chỉ định lại biến

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    83 để tạo thực thể cho một lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22 nhận đối số

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    95

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    96 và một đối số

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    97, và sau đó gọi phương thức

    fun main[] { }

    19 trên tham chiếu đối tượng

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    83:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

8

  1. Chạy mã.

Kết quả sẽ như sau:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

9

Đây là một ví dụ về tính đa hình. Mã này gọi phương thức

fun main[] {
}

19 trên biến thuộc loại

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8 và tuỳ thuộc vào giá trị thực tế của biến đó, bạn có thể thực thi các quy trình triển khai khác nhau của phương thức

fun main[] {
}

19.

Sử dụng lại mã lớp cấp cao trong các lớp con bằng từ khoá

class SmartDevice {
    fun turnOn[] {
    }
}

03

Khi xem xét kỹ phương thức

fun main[] {
}

19 và

fun main[] {
}

20, bạn nhận thấy biến

fun main[] {
}

64 có điểm giống nhau trong cách nó được cập nhật, bất cứ khi nào phương thức được gọi trong lớp con

class SmartDevice {
    // empty body
}
fun main[] {
}

21 và

class SmartDevice {
    // empty body
}
fun main[] {
}

22: mã bị trùng lặp. Bạn có thể sử dụng lại mã khi cập nhật trạng thái trong lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8.

Để gọi phương thức bị ghi đè trong lớp cấp cao từ lớp con, bạn cần sử dụng từ khoá

class SmartDevice {
    fun turnOn[] {
    }
}

03. Việc gọi một phương thức từ lớp cấp cao cũng tương tự như gọi phương thức từ bên ngoài lớp. Thay vì dùng toán tử

fun main[] {
}

44 giữa đối tượng và phương thức, bạn cần dùng từ khoá

class SmartDevice {
    fun turnOn[] {
    }
}

03 để thông báo cho trình biên dịch Kotlin gọi phương thức trên lớp cấp cao thay vì lớp con.

Cú pháp để gọi phương thức từ lớp cấp cao bắt đầu bằng từ khoá

class SmartDevice {
    fun turnOn[] {
    }
}

03, theo sau là toán tử

fun main[] {
}

44, tên hàm và một cặp dấu ngoặc đơn. Nếu có thể, dấu ngoặc đơn có bao gồm các đối số. Bạn có thể xem cú pháp trong sơ đồ này:

Sử dụng lại mã trong lớp cấp cao

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8:

  1. Xoá các câu lệnh

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    7 khỏi phương thức

    fun main[] { }

    19 và

    fun main[] { }

    20, đồng thời di chuyển mã trùng lặp từ lớp con

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21 và

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22 sang lớp cấp cao

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
    fun turnOff[] {
        println["Smart device is turned off."]
    }
}

0

  1. Dùng từ khoá

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    03 để gọi các phương thức từ lớp

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8 trong các lớp con

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21 và

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
    fun turnOff[] {
        println["Smart device is turned off."]
    }
}

1

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
    fun turnOff[] {
        println["Smart device is turned off."]
    }
}

2

Ghi đè các thuộc tính lớp cấp cao từ lớp con

Tương tự như phương thức, bạn cũng có thể ghi đè các thuộc tính theo các bước tương tự.

Ghi đè thuộc tính

class SmartDevice {
    fun turnOn[] {
    }
}

26:

  1. Trong lớp cấp cao

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8 trên dòng sau thuộc tính

    fun main[] { }

    64, hãy dùng từ khoá

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    28 và

    fun main[] { }

    07 để xác định thuộc tính

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    26 được đặt thành chuỗi

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    32:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
    fun turnOff[] {
        println["Smart device is turned off."]
    }
}

3

  1. Trong lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21, hãy dùng từ khoá

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    57 và

    fun main[] { }

    07 để xác định thuộc tính

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    26 được đặt thành chuỗi

    fun main[] { }

    28

    fun main[] { }

    60:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
    fun turnOff[] {
        println["Smart device is turned off."]
    }
}

4

  1. Trong lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22, hãy dùng từ khoá

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    57 và

    fun main[] { }

    07 để xác định thuộc tính

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    26 được đặt thành chuỗi

    fun main[] { }

    28

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    96:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
    fun turnOff[] {
        println["Smart device is turned off."]
    }
}

5

8. Đối tượng sửa đổi chế độ hiển thị

Hệ số sửa đổi chế độ hiển thị đóng vai trò quan trọng để hoàn thiện đóng gói:

  • Trong lớp, nó cho phép bạn ẩn các thuộc tính và phương thức khỏi quyền truy cập trái phép từ bên ngoài lớp.
  • Trong gói, nó cho phép bạn ẩn các lớp và giao diện khỏi quyền truy cập trái phép từ bên ngoài gói.

Kotlin cung cấp 4 hệ số sửa đổi chế độ hiển thị:

  • Đối tượng sửa đổi chế độ hiển thị mặc định

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    45.. Cho phép khai báo có thể truy cập ở mọi nơi. Các thuộc tính và phương thức bạn muốn dùng bên ngoài lớp sẽ được đánh dấu công khai.
  • class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    46. Cho phép khai báo có thể truy cập trong cùng một lớp hoặc tệp nguồn.

Có một số thuộc tính và phương thức chỉ được dùng bên trong lớp đó và bạn không nhất thiết muốn các lớp khác sử dụng. Bạn có thể đánh dấu các thuộc tính và phương thức này bằng đối tượng sửa đổi chế độ hiển thị

class SmartDevice {
    fun turnOn[] {
    }
}

46 để đảm bảo một lớp khác không thể vô tình truy cập vào.

  • class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    48. Cho phép khai báo có thể truy cập trong các lớp con. Các thuộc tính và phương thức bạn muốn dùng trong lớp xác định các lớp đó và lớp con được đánh dấu bằng đối tượng sửa đổi chế độ hiển thị

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    48.
  • class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    50. Cho phép khai báo có thể truy cập được trong cùng một mô-đun. Đối tượng sửa đổi nội bộ cũng giống như đối tượng sửa đổi riêng tư, nhưng bạn có thể truy cập vào các thuộc tính và phương thức nội bộ từ bên ngoài lớp, miễn là đối tượng này được truy cập trong cùng một mô-đun.

Khi bạn xác định một lớp, lớp này sẽ hiển thị công khai và bất kỳ gói nào nhập lớp đều có thể truy cập, tức là lớp đó ở chế độ công khai theo mặc định, trừ khi bạn chỉ định đối tượng sửa đổi chế độ hiển thị. Tương tự, khi bạn xác định hoặc khai báo các thuộc tính và phương thức trong lớp, theo mặc định, những thuộc tính và phương thức này có thể được truy cập bên ngoài lớp thông qua đối tượng lớp. Điều cần thiết là phải xác định chế độ hiển thị thích hợp cho mã, chủ yếu để ẩn các thuộc tính và phương thức các lớp khác không cần thiết truy cập.

Ví dụ: hãy xem cách người lái xe có thể sử dụng ô tô. Theo mặc định, những chi tiết bộ phận tạo nên một chiếc xe ô tô và cách xe hoạt động được ẩn giấu bên trong. Chiếc xe ô tô được thiết kế để vận hành trực quan nhất có thể. Bạn không muốn ô tô hoạt động phức tạp như một máy bay thương mại, tương tự như việc bạn không muốn một nhà phát triển khác hoặc bản thân bạn trong tương lai bị nhầm lẫn về cách sử dụng thuộc tính và phương pháp của một lớp.

Đối tượng sửa đổi chế độ hiển thị giúp bạn hiển thị các phần mã liên quan đến các lớp khác trong dự án và đảm bảo loại trừ việc triển khai một cách vô tình, điều này giúp mã dễ hiểu và ít xảy ra lỗi hơn.

Bạn phải đặt đối tượng sửa đổi chế độ hiển thị trước cú pháp khai báo, đồng thời khai báo lớp, phương thức hoặc thuộc tính như có thể thấy trong sơ đồ dưới đây:

Xác định đối tượng sửa đổi chế độ hiển thị cho các thuộc tính

Cú pháp để xác định đối tượng sửa đổi chế độ hiển thị cho một thuộc tính bắt đầu bằng đối tượng sửa đổi

class SmartDevice {
    fun turnOn[] {
    }
}

46,

class SmartDevice {
    fun turnOn[] {
    }
}

48 hoặc

class SmartDevice {
    fun turnOn[] {
    }
}

50, theo sau là cú pháp xác định thuộc tính. Bạn có thể xem cú pháp trong sơ đồ này:

Ví dụ: bạn có thể xem cách thiết lập thuộc tính

fun main[] {
}

64 thành riêng tư trong đoạn mã này:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
    fun turnOff[] {
        println["Smart device is turned off."]
    }
}

6

Bạn cũng có thể đặt hệ số sửa đổi chế độ hiển thị thành các hàm setter. Đối tượng sửa đổi được đặt trước từ khoá

class SmartDevice {
    fun turnOn[] {
    }
}

55. Bạn có thể xem cú pháp trong sơ đồ này:

Đối với lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8, giá trị của thuộc tính

fun main[] {
}

64 phải đọc được bên ngoài lớp thông qua các đối tượng lớp. Tuy nhiên, chỉ có lớp và các lớp con mới có thể cập nhật hoặc ghi giá trị. Để triển khai yêu cầu này, bạn cần phải sử dụng đối tượng sửa đổi

class SmartDevice {
    fun turnOn[] {
    }
}

48 trên hàm

fun main[] {
}

76 của thuộc tính

fun main[] {
}

64.

Dùng đối tượng sửa đổi

class SmartDevice {
    fun turnOn[] {
    }
}

48 trên hàm

fun main[] {
}

76 của thuộc tính

fun main[] {
}

64:

  1. Trong thuộc tính

    fun main[] { }

    64 của lớp cấp cao

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8, thêm hệ số sửa đổi

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    48 vào hàm

    fun main[] { }

    76:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
    fun turnOff[] {
        println["Smart device is turned off."]
    }
}

7

Bạn hiện không thực hiện bất kỳ hành động hoặc bước kiểm tra nào trong hàm

fun main[] {
}

76. Bạn chỉ cần chỉ định tham số

fun main[] {
}

90 cho biến

fun main[] {
}

87. Như bạn đã được học, điều này tương tự như cách triển khai mặc định cho phương thức setter thuộc tính. Trong trường hợp này, bạn có thể bỏ qua dấu ngoặc đơn và nội dung của hàm

fun main[] {
}

76:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
    fun turnOff[] {
        println["Smart device is turned off."]
    }
}

8

  1. Trong lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    71, hãy xác định một thuộc tính

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    73 được đặt thành giá trị

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    16 bằng một hàm setter riêng tư:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
    fun turnOff[] {
        println["Smart device is turned off."]
    }
}

9

  1. Thêm thuộc tính

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    73 theo sau là toán tử số học

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    76 vào phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    82 và

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    03. Sau đó, thêm thuộc tính

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    73 theo sau là toán tử số học

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    80 vào phương thức

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    86 và

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    
    }

    06:

class SmartDevice {
    fun turnOn[] {
        // A valid use case to call the turnOff[] method could be to turn off the TV when available power doesn't meet the requirement.
        turnOff[]
        ...
    }
    ...
}

0

Chỉ định truy cập cho các phương thức

Cú pháp để chỉ định một đối tượng sửa đổi mức độ hiển thị cho một phương thức bắt đầu bằng đối tượng sửa đổi

class SmartDevice {
    fun turnOn[] {
    }
}

46,

class SmartDevice {
    fun turnOn[] {
    }
}

48 hoặc

class SmartDevice {
    fun turnOn[] {
    }
}

50, theo sau là cú pháp xác định một phương thức. Bạn có thể xem cú pháp trong sơ đồ này:

Ví dụ: bạn có thể xem cách chỉ định một đối tượng sửa đổi

class SmartDevice {
    fun turnOn[] {
    }
}

48 cho phương thức

class SmartDevice {
    // empty body
}
fun main[] {
}

49 trong lớp

class SmartDevice {
    // empty body
}
fun main[] {
}

21 trong đoạn mã này:

class SmartDevice {
    fun turnOn[] {
        // A valid use case to call the turnOff[] method could be to turn off the TV when available power doesn't meet the requirement.
        turnOff[]
        ...
    }
    ...
}

1

Đối tượng sửa đổi chế độ hiển thị cho các hàm khởi tạo

Cú pháp để chỉ định đối tượng sửa đổi chế độ hiển thị cho hàm khởi tạo tương tự như cách xác định hàm khởi tạo chính với một vài điểm khác biệt:

  • Đối tượng sửa đổi được chỉ định sau tên lớp, nhưng trước từ khoá

    fun main[] { }

    97.
  • Nếu cần chỉ định đối tượng sửa đổi cho hàm khởi tạo chính, bạn cần phải giữ từ khoá

    fun main[] { }

    97 và dấu ngoặc đơn ngay cả khi không có bất kỳ tham số nào.

Bạn có thể xem cú pháp trong sơ đồ này:

Ví dụ: bạn có thể xem cách thêm đối tượng sửa đổi

class SmartDevice {
    fun turnOn[] {
    }
}

48 vào hàm khởi tạo

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8 trong đoạn mã dưới đây:

class SmartDevice {
    fun turnOn[] {
        // A valid use case to call the turnOff[] method could be to turn off the TV when available power doesn't meet the requirement.
        turnOff[]
        ...
    }
    ...
}

2

Đối tượng sửa đổi chế độ hiển thị cho các lớp

Cú pháp để chỉ định đối tượng sửa đổi chế độ hiển thị cho một lớp bắt đầu bằng đối tượng sửa đổi

class SmartDevice {
    fun turnOn[] {
    }
}

46,

class SmartDevice {
    fun turnOn[] {
    }
}

48 hoặc

class SmartDevice {
    fun turnOn[] {
    }
}

50, theo sau là cú pháp xác định một lớp. Bạn có thể xem cú pháp trong sơ đồ này:

Ví dụ: bạn có thể xem cách chỉ định đối tượng sửa đổi

class SmartDevice {
    fun turnOn[] {
    }
}

50 cho lớp

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
    smartTvDevice.turnOff[]
}

8 trong đoạn mã dưới đây:

class SmartDevice {
    fun turnOn[] {
        // A valid use case to call the turnOff[] method could be to turn off the TV when available power doesn't meet the requirement.
        turnOff[]
        ...
    }
    ...
}

3

Tốt nhất là bạn nên cố gắng hiển thị nghiêm ngặt các thuộc tính và phương thức, vì vậy, hãy khai báo chúng bằng đối tượng sửa đổi

class SmartDevice {
    fun turnOn[] {
    }
}

46 thường xuyên nhất có thể. Nếu bạn không thể đặt những email này ở chế độ riêng tư, hãy dùng hệ số sửa đổi

class SmartDevice {
    fun turnOn[] {
    }
}

48. Nếu bạn không thể bảo vệ những dữ liệu đó, hãy dùng hệ số sửa đổi

class SmartDevice {
    fun turnOn[] {
    }
}

50. Nếu bạn không thể giữ chúng trong nội bộ, hãy sử dụng hệ số sửa đổi

class SmartDevice {
    fun turnOn[] {
    }
}

45.

Chỉ định đối tượng sửa đổi chế độ hiển thị phù hợp

Bảng này giúp bạn xác định đối tượng sửa đổi chế độ hiển thị phù hợp dựa trên vị trí mà thuộc tính hay phương thức của một lớp hoặc hàm khởi tạo có thể truy cập được:

Ký tự bổ trợ

Có thể truy cập trong cùng một lớp

Có thể truy cập trong lớp con

Có thể truy cập được trong cùng mô-đun

Có thể truy cập ô-đun bên ngoài

class SmartDevice {
    fun turnOn[] {
    }
}

46

𝗫

𝗫

𝗫

class SmartDevice {
    fun turnOn[] {
    }
}

48

𝗫

𝗫

class SmartDevice {
    fun turnOn[] {
    }
}

50

𝗫

class SmartDevice {
    fun turnOn[] {
    }
}

45

Trong lớp con

class SmartDevice {
    // empty body
}
fun main[] {
}

21, bạn không nên cho phép kiểm soát các thuộc tính

fun main[] {
}

72 và

class SmartDevice {
    // empty body
}
fun main[] {
}

40 từ bên ngoài lớp. Bạn chỉ nên kiểm soát các thuộc tính này thông qua các phương thức

class SmartDevice {
    // empty body
}
fun main[] {
}

43 và

class SmartDevice {
    // empty body
}
fun main[] {
}

49.

Tương tự, trong lớp con

class SmartDevice {
    // empty body
}
fun main[] {
}

22, thuộc tính

class SmartDevice {
    // empty body
}
fun main[] {
}

59 chỉ nên được kiểm soát thông qua phương thức

fun main[] {
    val smartTvDevice = SmartDevice[]
}

10.

Thêm hệ số xác định mức độ hiển thị phù hợp vào các lớp con

class SmartDevice {
    // empty body
}
fun main[] {
}

21 và

class SmartDevice {
    // empty body
}
fun main[] {
}

22:

  1. Trong lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21, hãy thêm một đối tượng sửa đổi chế độ hiển thị

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    46 vào các thuộc tính

    fun main[] { }

    72 và

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    40:

class SmartDevice {
    fun turnOn[] {
        // A valid use case to call the turnOff[] method could be to turn off the TV when available power doesn't meet the requirement.
        turnOff[]
        ...
    }
    ...
}

4

  1. Trong lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22, hãy thêm một đối tượng sửa đổi

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    46 vào thuộc tính

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    59:

class SmartDevice {
    fun turnOn[] {
        // A valid use case to call the turnOff[] method could be to turn off the TV when available power doesn't meet the requirement.
        turnOff[]
        ...
    }
    ...
}

5

9. Xác định lớp uỷ quyền thuộc tính

Bạn đã tìm hiểu trong phần trước rằng các thuộc tính trong Kotlin sử dụng một trường sao lưu để lưu giữ giá trị của các thuộc tính đó trong bộ nhớ. Bạn sử dụng mã nhận dạng

fun main[] {
}

87 để tham chiếu mã này.

Khi xem mã cho đến thời điểm, bạn có thể thấy nhân bản mã để kiểm tra xem liệu các giá trị có nằm trong phạm vi cho thuộc tính

fun main[] {
}

72,

class SmartDevice {
    // empty body
}
fun main[] {
}

40 và

class SmartDevice {
    // empty body
}
fun main[] {
}

59 trong lớp

class SmartDevice {
    // empty body
}
fun main[] {
}

21 và

class SmartDevice {
    // empty body
}
fun main[] {
}

22. Bạn có thể sử dụng lại mã kiểm tra phạm vi trong hàm setter bằng lệnh ủy quyền. Thay vì sử dụng một trường, cũng như một hàm getter và setter để quản lý giá trị, lớp uỷ quyền sẽ quản lý giá trị đó.

Cú pháp để tạo uỷ quyền thuộc tính bắt đầu bằng phần khai báo một biến theo sau là từ khoá

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
}

9 và đối tượng uỷ quyền xử lý các hàm setter và getter cho thuộc tính. Bạn có thể xem cú pháp trong sơ đồ này:

Trước khi triển khai lớp mà bạn có thể uỷ quyền để triển khai, bạn cần làm quen với giao diện. Giao diện là một "hợp đồng" mà các lớp triển khai nó này cần phải tuân thủ. Nó tập trung vào việc nên làm thay vì cách thực hiện hành động. Tóm lại, giao diện sẽ giúp bạn đạt được sự trừu tượng.

Ví dụ: trước khi xây nhà, bạn phải thông tin cho kiến trúc sư về những gì bạn muốn. Bạn muốn có phòng ngủ, phòng cho trẻ em, phòng khách, bếp và một vài phòng tắm. Một cách ngắn gọn, bạn xác định những điều bạn muốn và kiến trúc sư chỉ định cách đạt được mục tiêu này. Bạn có thể xem cú pháp để tạo giao diện trong sơ đồ này:

Bạn đã biết cách mở rộng lớp và ghi đè chức năng của lớp đó. Với các giao diện, lớp triển khai giao diện. Lớp cung cấp thông tin triển khai cho các phương thức và thuộc tính được khai báo trong giao diện. Bạn sẽ thực hiện một thao tác tương tự với giao diện

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

30 để tạo lớp uỷ quyền. Bạn sẽ tìm hiểu thêm về các giao diện trong bài sau.

Để tạo lớp ủy quyền cho loại

fun main[] {
}

08, bạn cần triển khai giao diện

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

30. Tương tự, bạn cần triển khai giao diện

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

33 cho loại

fun main[] {
}

07.

Tạo ủy quyền cho loại

fun main[] {
}

08:

  1. Trước hàm

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    8, tạo một lớp

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    37 sẽ triển khai giao diện

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    38

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    39:

class SmartDevice {
    fun turnOn[] {
        // A valid use case to call the turnOff[] method could be to turn off the TV when available power doesn't meet the requirement.
        turnOff[]
        ...
    }
    ...
}

6

Đừng lo lắng về dấu ngoặc nhọn hoặc nội dung bên trong nó. Chúng biểu thị các loại chung và bạn sẽ tìm hiểu về chúng trong bài tiếp theo.

  1. Trong hàm khởi tạo chính của lớp

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    37, hãy thêm một tham số

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    41, một thuộc tính

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    42 riêng tư và một thuộc tính

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    43 riêng tư, tất cả đều thuộc loại

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    2:

class SmartDevice {
    fun turnOn[] {
        // A valid use case to call the turnOff[] method could be to turn off the TV when available power doesn't meet the requirement.
        turnOff[]
        ...
    }
    ...
}

7

  1. Trong phần nội dung của lớp

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    37, hãy ghi đè các phương thức

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    46 và

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    47:

class SmartDevice {
    fun turnOn[] {
        // A valid use case to call the turnOff[] method could be to turn off the TV when available power doesn't meet the requirement.
        turnOff[]
        ...
    }
    ...
}

8

Các phương thức này đóng vai trò là hàm getter và setter của các thuộc tính.

  1. Trên dòng trước lớp

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8, hãy nhập giao diện

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    30 và

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    50:

class SmartDevice {
    fun turnOn[] {
        // A valid use case to call the turnOff[] method could be to turn off the TV when available power doesn't meet the requirement.
        turnOff[]
        ...
    }
    ...
}

9

  1. Trong lớp

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    37, trên dòng trước phương thức

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    46, hãy xác định một thuộc tính

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    53 và khởi tạo thuộc tính đó bằng tham số

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    41:

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
}

0

Thuộc tính này đóng vai trò là trường sao lưu cho biến.

  1. Trong phần nội dung của phương thức

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    46, trả thuộc tính

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    53 về:

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
}

1

  1. Trong phần nội dung của phương thức

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    47, hãy kiểm tra xem tham số

    fun main[] { }

    90 đang được chỉ định có nằm trong phạm vi

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    59 hay không trước khi bạn chỉ định cho thuộc tính

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    53:

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
}

2

  1. Trong lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21, hãy dùng lớp ủy quyền để xác định các thuộc tính

    fun main[] { }

    72 và

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    40:

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
}

3

  1. Trong lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22, hãy dùng lớp ủy quyền để xác định thuộc tính

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    59:

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
}

4

10. Thử nghiệm giải pháp

Bạn có thể xem mã giải pháp trong đoạn mã này:

fun main[] {
    val smartTvDevice = SmartDevice[]
    smartTvDevice.turnOn[]
}

5

Kết quả sẽ như sau:

class SmartDevice {
    fun turnOn[] {
        println["Smart device is turned on."]
    }
}

9

11. Tham gia thử thách này

  • Trong lớp

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    8, hãy xác định một phương thức

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    67 để in chuỗi

    fun main[] { }

    68

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    69

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    70

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    71

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    72

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    73

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    74.
  • Trong lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21, hãy xác định một phương thức

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    76 để giảm âm lượng và phương thức

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    77 chuyển về kênh trước đó.
  • Trong lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22, hãy xác định một phương thức

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    79 để giảm độ sáng.
  • Trong lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    71, hãy đảm bảo bạn chỉ có thể thực hiện tất cả các hành động khi thuộc tính

    fun main[] { }

    64 của mỗi thiết bị được đặt thành một chuỗi

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    82. Ngoài ra, hãy đảm bảo bạn đã cập nhật chính xác thuộc tính

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    73.

Sau khi bạn hoàn tất việc triển khai:

  • Trong lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    71, xác định phương thức

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    85,

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    86,

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    87,

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    88 và

    class SmartDevice {

    fun turnOn[] {  
        println["Smart device is turned on."]  
    }  
    
    }

    89.
  • Gọi các phương thức thích hợp từ lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    21 và

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    22 trong lớp

    class SmartDevice {

    // empty body  
    
    } fun main[] { }

    71.
  • Trong hàm

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    
    }

    8, hãy gọi các phương thức được thêm này để kiểm tra chúng.

12. Kết luận

Xin chúc mừng! Bạn đã được học cách xác định lớp và tạo bản sao đối tượng . Bạn cũng đã được học cách tạo mối quan hệ giữa các lớp và uỷ quyền thuộc tính.

Tóm tắt

  • Có 4 nguyên tắc chính của OOP: đóng gói, tóm tắt, kế thừa và đa hình.
  • Các lớp được xác định bằng từ khóa

    fun main[] {

    val smartTvDevice = SmartDevice[]  
    smartTvDevice.turnOn[]  
    smartTvDevice.turnOff[]  
    
    }

    0, đồng thời chứa các thuộc tính và phương thức.
  • Thuộc tính tương tự như biến, ngoại trừ các thuộc tính có thể có phương thức getter và setter tuỳ chỉnh.
  • Hàm khởi tạo sẽ chỉ định cách tạo thực thể của đối tượng cho lớp.
  • Bạn có thể bỏ qua từ khóa

    fun main[] { }

    97 khi xác định một hàm khởi tạo chính.
  • Tính kế thừa giúp bạn dễ dàng tái sử dụng mã.
  • Mối quan hệ IS-A đề cập đến tính kế thừa.
  • Mối quan hệ HAS-A đề cập đến tính liên kết.
  • Hệ số xác định mức độ hiển thị đóng vai trò quan trọng trong việc hoàn thành đóng gói.
  • Kotlin cung cấp 4 hệ số xác định mức độ hiển thị:

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    45,

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    46,

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    48 và

    class SmartDevice {

    fun turnOn[] {  
    }  
    
    }

    50.
  • Ủy quyền thuộc tính cho phép bạn tái sử dụng mã getter và setter trong nhiều lớp.

Tìm hiểu thêm

  • Tích hợp ủy quyền

Trừ khi có lưu ý khác, nội dung của trang này được cấp phép theo Giấy phép ghi nhận tác giả 4.0 của Creative Commons và các mẫu mã lập trình được cấp phép theo Giấy phép Apache 2.0. Để biết thông tin chi tiết, vui lòng tham khảo Chính sách trang web của Google Developers. Java là nhãn hiệu đã đăng ký của Oracle và/hoặc các đơn vị liên kết với Oracle.

[{ "type": "thumb-down", "id": "missingTheInformationINeed", "label":"Thiếu thông tin tôi cần" },{ "type": "thumb-down", "id": "tooComplicatedTooManySteps", "label":"Quá phức tạp/quá nhiều bước" },{ "type": "thumb-down", "id": "outOfDate", "label":"Đã lỗi thời" },{ "type": "thumb-down", "id": "translationIssue", "label":"Vấn đề về bản dịch" },{ "type": "thumb-down", "id": "samplesCodeIssue", "label":"Vấn đề về mẫu/mã" },{ "type": "thumb-down", "id": "otherDown", "label":"Khác" }] [{ "type": "thumb-up", "id": "easyToUnderstand", "label":"Dễ hiểu" },{ "type": "thumb-up", "id": "solvedMyProblem", "label":"Giúp tôi giải quyết được vấn đề" },{ "type": "thumb-up", "id": "otherUp", "label":"Khác" }]

Chủ Đề