CodeGym /Các khóa học /Kotlin SELF /`enum class`: gia tri, tham so, phuong thuc va quy tac kh...

`enum class`: gia tri, tham so, phuong thuc va quy tac khai bao

Kotlin SELF
Mức độ, Bài học
Có sẵn

1. Vi sao can enum class

Neu ban tung viet thu gi do nhu if (category == "food"), thi ban da dang di tren con duong dan toi “co ac co dai” mang ten “chuoi ma thuat”. Chung “ma thuat” vi chi can mot loi go nham la logic bien thanh qua bi: "Food", "FOOD", "food " va "fod" trong mat nguoi thi gan nhu giong nhau, nhung voi chuong trinh thi la cac gia tri khac nhau. Ket qua: chuong trinh khong bi compiler bao loi — no “vo” vi doi.

enum class la cach noi voi compiler: “Day la danh sach day du cac lua chon hop le. Khong the co lua chon nao khac”. Va sau do Kotlin bat dau giup ban: kiem tra kieu, goi y cac lua chon trong IDE, canh bao neu ban co gang gan mot thu “khong nam trong danh sach”.

Hay tuong tuong mot bang nho de cam nhan su khac biet:

Cach lam Ta luu gi Co the gap su co gi
Chuoi
"FOOD", "food", "food (VI)"
go nham, khac hoa/thuong, khac ngon ngu, khoang trang
enum class
Category.FOOD
gan nhu chi con loi khi phan tich du lieu nguoi dung nhap (va co the giai quyet)

Them mot vi du gan gui: danh muc chi tieu. Neu ban luu danh muc bang chuoi, thi mot ngay nao do ban se co dong thoi "Transport" va "TRANSPORT", va bao cao “theo danh muc” bat ngo hien ra hai danh muc gan giong nhau. Day khong phai bug, day la “dac tinh cua dau vao nguoi dung”, nhung nguoi phai chiu tran la ban.

enum toi thieu

Khi nhac den “enum”, nguoi ta thuong tuong tuong den thu gi do dang so va “doanh nghiep”. Thuc te thi dang co ban rat don gian: ban liet ke cac lua chon bang dau phay. Moi lua chon (con duoc goi la enum entry, tuc “gia tri cua enum”) la mot gia tri san sang thuoc kieu enum.

Day la vi du toi thieu:

enum class Status { NEW, IN_PROGRESS, DONE }

fun main() {
    val s: Status = Status.DONE
    println(s) // DONE
}

O day Status.DONE khong phai chuoi, khong phai so, cung khong phai “chi la van ban”. No la mot gia tri co kieu Status. Va Kotlin gio se khong cho phep ban vo tinh gan vao do thu gi khac:

enum class Status { NEW, IN_PROGRESS, DONE }

fun main() {
    val s: Status = Status.DONE
    // s = "DONE" // khong duoc: kieu String khong phu hop
}

Y quan trong: enum la “mot kieu voi tap gia tri co dinh”. Chinh vi vay enum rat hop de thay the chuoi o nhung noi “cac lua chon da biet truoc”.

name va ordinal

Khi ban in enum bang println(s), Kotlin thuong in ra ten cua entry (DONE). Dieu nay khong phai ngau nhien: moi gia tri enum deu co cac thuoc tinh tieu chuan name va ordinal. name la ten chuoi cua hang so, con ordinal la so thu tu cua no, bat dau tu 0. Day la hanh vi tieu chuan cua enum trong Kotlin.

Thu xem:

enum class Status { NEW, IN_PROGRESS, DONE }

fun main() {
    println(Status.NEW.name)       // NEW
    println(Status.NEW.ordinal)    // 0
    println(Status.DONE.ordinal)   // 2
}

name thuong huu ich cho debug va in ra don gian. Con ordinal nghe co ve hap dan (“o, chi so mien phi!”), nhung do la cai bay.

Tuong tuong: ban luu ordinal vao file nhu “ma trang thai”, sau do ban quyet dinh doi thu tu cac entry:

enum class Status { NEW, DONE, IN_PROGRESS } // doi thu tu

Va the la xong: gio DONE co ordinal khac. Nghia la du lieu cu se bi doc sai. Vi vay, khong the xem ordinal la dinh danh on dinh neu thu tu co the thay doi (va gan nhu luc nao cung co the — it nhat la vi ban muon “dep hon”).

Neu can dinh danh on dinh, hay khai bao ro rang no la tham so/thuoc tinh cua enum.

Tat ca lua chon enum: entries, values() va valueOf

Rat som se co cau hoi thuc te: “Lam sao hien thi cho nguoi dung danh sach tat ca danh muc?” hoac “Lam sao duyet het cac lua chon?”. Enum cung cap cac cach “tong hop” (tuc do compiler tu dong sinh ra) de lay “tat ca gia tri cua enum”.

Kotlin hien dai cung cap thuoc tinh entries, tra ve mot danh sach chuyen biet chua tat ca entry.

Vi du:

enum class Category { FOOD, TRANSPORT, BOOKS }

fun main() {
    for (c in Category.entries) {
        println(c.name)
    }
    // FOOD
    // TRANSPORT
    // BOOKS
}

Truoc day (va trong nhieu vi du cu tren internet) ban se thay values() — no tra ve mot mang. Nhung hien tai entries duoc xem la tot hon: no khong tao mang moi moi lan goi va nhin “giong collection” hon. Kotlin cung chinh thuc ghi chu rang truoc khi co entries thi nguoi ta dung values().

Mot thu huu ich nua la valueOf("NAME"), tra ve enum theo ten chuoi. Nhung no co “tinh cach”: neu truyen vao ten khong hop le, no se nem IllegalArgumentException. Tuc la valueOf la “phan tich nghiem ngat”, phu hop khi ban chac chan ve du lieu.

Enum co tham so

Den luc nay enum trong nhu chi la danh sach tu. Nhung trong du an thuc te thuong can moi entry co “mo ta rieng”, “ma”, “ten than thien”, “gioi han”, v.v. Va day la phan hay: enum co the co tham so constructor — gan nhu mot class binh thuong.

Hay lam danh muc chi tieu “than thien hon”: voi ten hien thi va, vi du, ma on dinh.

enum class Category(val code: Int, val title: String) {
    FOOD(10, "Do an"),
    TRANSPORT(20, "Di chuyen"),
    BOOKS(30, "Sach")
}

fun main() {
    println(Category.FOOD.title)   // Do an
    println(Category.FOOD.code)    // 10
}

Gio thay vi ordinal ta co code, va no on dinh: chinh ta tu dat. Ban muon doi thu tu entry hay them entry moi — code khong tu doi. Day la cach rat tot neu ban du dinh luu danh muc ra ben ngoai: vao file, vao database, gui qua mang.

Con title la thu ban se hien cho nguoi dung trong giao dien hoac bao cao, de khong phai in cap lock TRANSPORT (du tat nhien, neu ban thich phong cach “ke toan la het”, thi cung khong sao).

Phuong thuc ben trong enum

Du lieu thi tot, nhung doi khi ban muon moi entry lam duoc gi do huu ich. Dieu nay hoan toan binh thuong: enum la mot class, va cac gia tri cua no la cac object cua class do. Nghia la enum co the co phuong thuc su dung cac tham so (code, title, v.v.).

Hay lam mot phuong thuc de format danh muc khi hien thi:

enum class Category(val code: Int, val title: String) {
    FOOD(10, "Do an"),
    TRANSPORT(20, "Di chuyen"),
    BOOKS(30, "Sach");

    fun label(): String = "$title (#$code)"
}

fun main() {
    println(Category.TRANSPORT.label()) // Di chuyen (#20)
}

Chu y dau ; sau danh sach entry. Day khong phai dau cham phay “cho co ve nghiem tuc”, ma la quy tac cu phap: neu enum co than (phuong thuc, thuoc tinh), thi sau entry cuoi cung bat buoc can dau phan tach ;.

Vi sao? Vi neu khong thi parser kho xac dinh danh sach hang so ket thuc o dau va thanh vien class bat dau o dau. Kotlin co gang giu loi compile de hieu, thay vi “co gi do sai o tan cung vu tru”.

Dau phay va ; trong enum

Trong thuc te, dau kho nhat voi enum khong nam o y tuong hay logic, ma nam o “tai sao no khong compile, minh chi them mot phuong thuc thoi ma”. Thuong cau tra loi la: “vi quen ;”.

Co the nho quy tac the nay: khi ban chi liet ke cac entry — do la “danh sach” ngan cach boi dau phay. Ngay khi ban muon them bat cu thu gi (phuong thuc/thuoc tinh) — dat ;, va sau do la “phan than class binh thuong”.

Mau dung:

enum class Category(val title: String) {
    FOOD("Do an"),
    TRANSPORT("Di chuyen"),
    BOOKS("Sach");

    fun upperTitle(): String = title.uppercase()
}

Va mot chi tiet nho cung nhom: dau phay giua cac entry la bat buoc (tru entry cuoi). Con ; dat sau entry cuoi neu ben duoi con co thanh vien class.

Neu IntelliJ to mau do va noi gi do nhu “Expecting member declaration” hoac “There must be a semicolon after the last enum entry” — gan nhu chac chan ban dang dung truong hop nay.

2. Vi du: enum trong ung dung console quan ly chi tieu

Gio hay lam thu huu ich nhat: ap dung enum khong chi “trong chan khong”, ma vao ung dung console hoc tap cua chung ta. Gia su ta da co mot mo hinh chi tieu don gian (ta da lam truoc do bang data class) va dau do trong chuong trinh ta luu danh sach chi tieu. Truoc day danh muc co the la chuoi, nhung ta muon an toan ve kieu.

Gioi thieu Category nhu enum

Bat dau tu co ban: liet ke cac danh muc. De nguoi dung de dung, ta gan cho moi danh muc mot “ten than thien”.

enum class Category(val title: String) {
    FOOD("Do an"),
    TRANSPORT("Di chuyen"),
    BOOKS("Sach")
}

Cap nhat mo hinh chi tieu

Gio Expense luu category: Category, thay vi String.

data class Expense(
    val amount: Int,
    val category: Category,
    val note: String
)

Phan tich danh muc tu dau vao mot cach an toan

Nguoi dung se nhap thu gi do nhu food hoac FOOD. Con Category.valueOf(...) thi doi hoi dung chinh xac ten va con co the nem exception.

Vi vay, voi “dau vao nguoi dung” nen lam phan tich mem: chuan hoa chuoi va tim trong entries.

Day la ham gon gang:

fun parseCategoryOrNull(raw: String): Category? {
    val key = raw.trim().uppercase()
    return Category.entries.firstOrNull { it.name == key }
}

O day entries cho ta danh sach tat ca entry. Neu nguoi dung nhap thu gi do khong hop le — se tra ve null, va sau do ta xu ly trong logic nhap lieu (khong bi crash).

De minh hoa, co the hinh dung mot so do nho:

flowchart TD
    A["Nguoi dung nhap chuoi"] --> B["trim()"]
    B --> C["uppercase()"]
    C --> D["tim trong Category.entries theo name"]
    D -->|tim thay| E["tra ve Category"]
    D -->|khong tim thay| F["tra ve null"]

Them chi tieu: doc → parse → tao object

Gop lai mot ham them chi tieu nho. Dinh dang don gian: so tien, danh muc, ghi chu (ghi chu la phan con lai cua dong).

fun addExpense(rawAmount: String, rawCategory: String, note: String): Expense? {
    val amount = rawAmount.trim().toIntOrNull() ?: return null
    val category = parseCategoryOrNull(rawCategory) ?: return null
    return Expense(amount = amount, category = category, note = note.trim())
}

Va test voi vi du nho:

fun main() {
    val e = addExpense("120", "food", "an trua") ?: return
    println(e) // Expense(amount=120, category=FOOD, note=an trua)
}

Tam thoi khi in ra, category se la FOOD vi do la name. Nhung voi nguoi dung, ta se hien thi title:

fun main() {
    val e = addExpense("120", "food", "an trua") ?: return
    println("${e.amount} ₣  — ${e.category.title} (${e.note})")
    // 120 ₣  — Do an (an trua)
}

Goi y cho nguoi dung: co nhung danh muc nao

Vi ta dung enum — ta co the de dang in ra danh sach danh muc:

fun printCategories() {
    val text = Category.entries.joinToString { it.name.lowercase() }
    println("Danh muc: $text")
    // Danh muc: food, transport, books
}

entries o day lai duoc dung nhu “nguon su that” cho tat ca lua chon.

Cach lam nay tot o cho: neu ban them danh muc HEALTH("Suc khoe"), phan goi y se tu dong cap nhat (va ban khong can nho xem minh da tu go danh sach chuoi o dau).

3. Cac loi thuong gap khi lam viec voi enum class

Loi so 1: tiep tuc luu lua chon bang chuoi “vi nhanh hon”.
Doi khi ban thay String don gian: doc, so sanh, xong. Nhung chi can co bao cao, loc, thong ke va it nhat mot nguoi dung nhap food co khoang trang o cuoi — ban se bat dau ton thoi gian de “chuan hoa chuoi” o hang chuc noi. Enum dua van de ve mot noi: phan tich dau vao. Con ben trong chuong trinh, gia tri se nghiem ngat va dong nhat.

Loi so 2: dung ordinal nhu mot dinh danh on dinh.
ordinal phu thuoc vao thu tu khai bao. Hom nay FOOD co ordinal = 0, ngay mai ban doi thu tu entry — va moi thu vo am tham, khong canh bao. ordinal chi nen dung cho nhung viec cuc ky cuc bo (vi du “hien thi vi tri trong danh sach ngay luc nay”), khong dung de luu tru va khong dung cho protocol. Neu can ma on dinh — hay them truong rieng, vi du code.

Loi so 3: quen ; truoc phuong thuc va thuoc tinh trong enum.
Day la tinh huong kinh dien: ban khai bao cac entry, sau do them phuong thuc — va compiler bat ngo bat loi “vo ly”. Nguyen nhan rat don gian: neu enum co thanh vien class, danh sach entry phai duoc tach bang ;. Day la quy tac Kotlin cho enum, va no that su bat buoc.

Loi so 4: parse dau vao nguoi dung bang valueOf() ma khong bao ve.
valueOf("FOOD") tien, nhung neu chuoi khong khop — no nem IllegalArgumentException. Voi “du lieu tu ben ngoai” (nguoi dung nhap), thuong can parse an toan: dung entries.firstOrNull { ... } de nhan null va hien thong bao de hieu, thay vi bi crash boi exception.

Loi so 5: tron “ten hien thi” voi name cua enum.
name la ten ky thuat cua hang so (FOOD), rat hop cho code va debug, nhung thuong khong than thien voi nguoi dung. Neu ban muon hien thi dep, hay them truong nhu title: String va hien thi no. Khi do giao dien khong bi phu thuoc vao ten ky thuat va ban co the thay doi cach hien thi ma khong can sua logic.

1
Nhiệm vụ
Kotlin SELF, mức độ, bài học
Đã khóa
Bảng tiến độ
Bảng tiến độ
1
Nhiệm vụ
Kotlin SELF, mức độ, bài học
Đã khóa
Tâm trạng bot
Tâm trạng bot
1
Nhiệm vụ
Kotlin SELF, mức độ, bài học
Đã khóa
Máy bán đồ uống
Máy bán đồ uống
1
Nhiệm vụ
Kotlin SELF, mức độ, bài học
Đã khóa
Chế độ chạy
Chế độ chạy
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION