Menu
CoddyTech

Lớp enum

Thuộc phần Lập trình hướng đối tượng trong hành trình Kotlin của Coddy. Bài học 33 trên 57.

enum class khai báo một kiểu có một tập giá trị cố định, gọi là các hằng số. Mỗi hằng số là một đối tượng của enum, có name và ordinal, tức vị trí bắt đầu từ 0. entries liệt kê các hằng số theo thứ tự:

enum class Direction { NORTH, EAST, SOUTH, WEST }

Bên trong main:

val d = Direction.EAST
println(d)
println(d.ordinal)
println(Direction.entries)

Đầu ra:

EAST
1
[NORTH, EAST, SOUTH, WEST]

Các hằng số enum có thể có thuộc tính được truyền vào hàm khởi tạo của enum, và enum có thể khai báo các phương thức. Dấu chấm phẩy kết thúc danh sách hằng số trước các thành viên:

enum class Coin(val cents: Int) {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25);

    fun label() = "${name.lowercase()} ($cents c)"
}

Bên trong main:

println(Coin.DIME.label())
println(Coin.entries.sumOf { it.cents })

Đầu ra:

dime (10 c)
41

Một câu lệnh when dùng với enum liệt kê mọi hằng số thì không cần else, và trình biên dịch sẽ báo nếu thiếu một hằng số. valueOf("SOUTH") tìm hằng số theo đúng tên và gây ngoại lệ nếu không tìm thấy, vì vậy đầu vào thường được đối chiếu bằng entries.find:

enum class Direction { NORTH, EAST, SOUTH, WEST }

fun turnRight(d: Direction) = when (d) {
    Direction.NORTH -> Direction.EAST
    Direction.EAST -> Direction.SOUTH
    Direction.SOUTH -> Direction.WEST
    Direction.WEST -> Direction.NORTH
}

fun parse(text: String) = Direction.entries.find { it.name == text.uppercase() }

Bên trong main:

println(turnRight(Direction.valueOf("SOUTH")))
println(parse("north"))
println(parse("up"))

Đầu ra:

WEST
NORTH
null

Một hằng số có thể có phần thân riêng và ghi đè một phương thức trong đó. Khai báo phương thức abstract trong enum buộc mọi hằng số phải triển khai phương thức đó:

enum class Op(val symbol: String) {
    PLUS("+") {
        override fun apply(a: Int, b: Int) = a + b
    },
    TIMES("*") {
        override fun apply(a: Int, b: Int) = a * b
    };

    abstract fun apply(a: Int, b: Int): Int
}

Bên trong main:

for (op in Op.entries) println("6 ${op.symbol} 3 = ${op.apply(6, 3)}")

Đầu ra:

6 + 3 = 9
6 * 3 = 18
challenge icon

Thử thách

Dễ

Hoàn thiện enum Size với các hằng số SMALL (250 ml, giá 300), MEDIUM (350 ml, 380) và LARGE (500 ml, 450), giá tính bằng cent. label() trả về medium (350 ml): 3.80, còn upsize() trả về kích cỡ lớn hơn tiếp theo, hoặc giữ nguyên kích cỡ nếu là LARGE. parse(text) của companion tìm kích cỡ theo tên, không phân biệt chữ hoa chữ thường, hoặc theo chữ cái đầu tiên (s, M), và trả về null nếu không tìm thấy.

Code được cung cấp đọc các đơn hàng như medium, L hoặc up small (đồ uống được tăng kích cỡ), rồi in từng nhãn hoặc unknown size x, cuối cùng in total: 11.10.

Code của bạn nằm trong Size.kt. Main.kt chứa code đầu vào/đầu ra được cung cấp và bạn không thể chỉnh sửa tệp này.

Tự làm thử

fun main() {
    // Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
    val input = generateSequence(::readLine).toList()
    var total = 0
    for (line in input) {
        val upsize = line.startsWith("up ")
        val size = Size.parse(line.removePrefix("up "))
        if (size == null) {
            println("unknown size $line")
            continue
        }
        val chosen = if (upsize) size.upsize() else size
        println(chosen.label())
        total += chosen.price
    }
    println("total: %d.%02d".format(total / 100, total % 100))
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Playground Kotlin