Nội dung
Khái niệm
Enum hay enumeration có thể hiểu là một kiểu giá trị và nó cho phép các lập trình viên có thể làm việc một cách an toàn trong mã với những dữ liệu đó.
Trong ngôn ngữ lập trình Swift, Enumeration được đánh giá là khá linh hoạt do chúng không phải cung cấp từng giá trị như chuỗi, ký tự, hoặc integer cho mỗi trường hợp của enumeration.
Ngoài ra, một tập hợp của các phần tử có giá trị khác nhau liên quan có thể được định nghĩa như một phần của enumeration. Không những thế Enumerations cũng có thể được hiểu như trình khởi tạo để cung cấp một giá trị phần tử ban đầu và được mở rộng để mở rộng chức năng của chúng.
Cú pháp:
//khai báo enum
//cách 1
enum testEnum{
case Trai
case Phai
case Tren
case Duoi
}
//cách 2
enum testEnum2{
case Dong,Tay,Nam,Bac
}
Ta có thể kết hợp enum với câu lệnh Switch như sau:
var timduong = testEnum.Phai
switch timduong{
case .Trai:
print(“Bên Trái”)
case .Phai:
print(“Bên Phải”)
case .Tren:
print(“Ở Trên”)
case .Duoi:
print(“Ở Dưới”)
}
//Kết quả: “Bên Phải”
Để rõ hơn vê enum chúng ta sẽ sử dụng ví dụ sau bạn có thể định nghĩa ra một tập hợp các ngày trong tuần (Thứ 2, thứ 3,… , chủ nhật).
Trong trường hợp không có hoặc enum không sử dụng được thì bạn có thể định nghĩa cả 7 hằng số trên để có 1 tập hợp các ngày trong tuần.
import Foundation
// Định nghĩa ra 7 hằng số, đại diện cho các ngày trong tuần.
let CONST_MONDAY = 2;
let CONST_TUESDAY = 3;
let CONST_WEDNESDAY = 4;
let CONST_THURSDAY = 5;
let CONST_FRIDAY = 6;
let CONST_SATURDAY = 7;
let CONST_SUNDAY = 1;
Một hàm mô phỏng lấy ra tên công việc sẽ làm ứng với ngày cụ thể trong tuần. (Giống kiểu thời khóa biểu)
import Foundation
// Tham số truyền vào là ngày trong tuần.
// Trả về tên công việc sẽ làm.
func getJobByDay(dayInWeek: Int) -> String {
if (dayInWeek == CONST_SATURDAY
|| dayInWeek == CONST_SUNDAY) {
return "Nothing";
}
return "Coding";
}
Theo tôi, việc code như trên chưa sẽ không được an toàn. Ví dụ như, chẳng may bạn nhập trùng các giá trị cho các ngày trong tuần. Hoặc gọi hàm getJobByDay(Int) mà truyền vào giá trị nằm ngoài các giá trị định nghĩa trước.
- Không phải là kiểu an toàn: Gọi method getJobByDay(Int) và truyền vào bất kỳ giá trị Int nào.
- Không có ý nghĩa trong in ấn: Nếu bạn muốn in ra các ngày trong tuần nó sẽ là các con số,thay vì một chữ có ý nghĩa như “MONDAY”.
Và đây là cách bạn tạo enum, một tập hợp đặc biệt.
WeekDay.swift
import Foundation
// Định nghĩa Enum WeekDay, một tập hợp đặc biệt.
enum WeekDay
{
// Các phần tử
case MONDAY
case TUESDAY
case WEDNESDAY
case THURSDAY
case FRIDAY
case SATURDAY
case SUNDAY
}
Ví dụ sử dụng Enum:
Duyệt trên các phần tử của Enum
Không có một hàm hoặc một phương thức sẵn có nào cho phép bạn lấy ra danh sách các phần tử của một Enum bất kỳ, nhưng bạn có thể tự định nghĩa một biến chứa tất cả các phần tử của Enum.
Ví dụ dưới đây định nghĩa một Enum, trong Enum này cũng định nghĩa một hằng số chứa tất cả các phần tử của nó.
import Foundation
// Các mùa trong năm.
enum Season {
case Spring
case Summer
case Autumn
case Winter
// Một hằng số tĩnh, chứa tất cả các phần tử (element) của Enum.
static let allValues = [Spring, Summer, Autumn, Winter]
}
import Foundation
func test_getAllSeasons() {
for season in Season.allValues {
print(season)
}
}
--> String
--> Summer
--> Autumn
--> Winter
Enum trong câu lệnh switch
import Foundation
func test_switchEnum() {
var day = WeekDay.THURSDAY;
switch (day) {
case .MONDAY:
print("Working day");
case .SATURDAY, .SUNDAY :
print("Holiday");
default:
print(day);
}
}
--> THURSDAY
Enum với các dữ liệu thô (raw value)
Dữ liệu thô được hiểu ở đây là kiểu String, character, Int, Number,… Một Enum như vậy mở rộng một trong các kiểu String, Character, Int,..
Ví dụ bạn có thể định nghĩa một Enum là tập hợp các tháng của năm, tập hợp này sẽ chứa các giá trị thô từ 1 đến 12.
import Foundation
// Định nghĩa một Enum là tập liệt kê các tháng trong năm.
// Nó mở rộng (extends) từ Int
enum Month : Int {
// Gán giá trị thô (raw value) cho phần tử đầu tiên.
// (Nếu một phần tử không được gán giá trị thô,
// Theo mặc định giá trị của nó là giá trị của phần tử đứng trước cộng thêm 1).
case January = 1,
February, March, April, May, June,
July, August, September, October, November, December
// Một hằng số tĩnh chứa tất cả các phần tử của enum Month.
static let allValues = [January,February, March,
April, May, June, July, August,
September, October, November, December]
}
//
enum Suit:String {
case Spades = "♠"
case Hearts = "♥"
case Diamonds = "♦"
case Clubs = "♣"
// Một hằng số tĩnh chứa tất cả các phần tử của enum Suit.
static let allValues = [Spades,Hearts,Diamonds,Clubs]
}
In ra các phần tử của enum Month, và các giá trị thô ( raw value) tương ứng.
import Foundation
func test_MonthEnum() {
// In tất cả các phần tử và giá trị thô (raw value) của Enum.
print("All element/raw value of Month enum");
for e in Month.allValues {
let rawValue = e.rawValue
print("Element \(e), raw value: \(rawValue)" );
}
print("---------------------");
// In tất cả các phần tử và giá trị thô (raw value) của Enum.
print("All element/raw value of Suit enum");
for e in Suit.allValues {
let rawValue = e.rawValue
print("Element \(e), raw value: \(rawValue)" );
}
}
Chạy ví dụ:
Enum với các giá trị liên hợp
Enum có thể được tạo với các phần tử khác nhau chứ các giá trị liên hợp với nó.
Tôi đưa ra một tình huống, bạn tạo ra một Enum chứa các hình thức khuyến mại:
- GIFT: Tặng quà
- DISCOUNT: Giảm giá
- MONEY: Tặng tiền
- SHIPPING: Miễn phí vận chuyển.
Vấn đề ở chỗ mỗi hình thức khuyến mại lại có các giá trị liên hợp với nó, chẳng hạn tặng quà ( GIFT) thì tặng gì, và số lượng bao nhiêu. Hoặc tặng tiền ( MONEY) thì số tiền tặng là bao nhiêu,…
Như vậy mỗi phần tử của Enum lại có các tham số khác nhau. Hãy xem ví dụ:
import Foundation
// Các kiểu khuyến mại.
enum Promotion {
// Tặng quà (Tên quà tặng và số lượng)
case GIFT (name: String, quantity: Int)
// Giảm giá (phần trăm: 0 - 100)
case DISCOUNT(percent: Int)
// Tặng tiền (Số tiền).
case MONEY(amount : Int)
// Miễn phí giao hàng.
case SHIPPING
}
Enum Promotion chỉ có 4 phần tử, bạn không thể thêm bớt các phần tử của nó, các giá trị liên hợp với các phần tử được xác định tại thời điểm chạy của chương trình.
import Foundation
// Mô phỏng việc mua hàng, và nhận khuyến mại.
func getRandomPromotion() -> Promotion {
// Một giá trị ngẫu nhiên
var random: UInt32 = arc4random()
// Phép chia cho 4 và lấy số dư (0, 1, 2, 3).
random = random % 4
switch random {
case 0:
return Promotion.DISCOUNT(percent: 10)
case 1:
return Promotion.GIFT(name: "Doll", quantity: 1)
case 2:
return Promotion.MONEY(amount: 100)
case 3:
return Promotion.SHIPPING
default:
return Promotion.SHIPPING
}
}
func test_Promotion() {
var myProm = getRandomPromotion()
print("Get Promotion: \(myProm)")
switch myProm {
case .DISCOUNT(let percent):
print("Percent is: \(percent)")
case .GIFT(let name, let quantity ):
print("Gift name: \(name), quantity: \(quantity)")
case .MONEY(let amount) :
print("Amount: \(amount)")
default:
print(myProm)
}
}
Chạy ví dụ:
Phương thức trong Enum
Bạn có thể định nghĩa các phương thức trong Enum, hãy xem ví dụ:
import Foundation
// Tiền tệ (Currency).
enum Currency {
case USD
case YEN
case VND
func description() -> String {
switch self {
case USD:
return "America's currency"
case YEN:
return "Japan's currency"
case VND :
return "Vietnam's currency"
}
}
}