Bài 14: Enumeration trong swift - Lập trình Swift cơ bản

Đăng bởi: Admin | Lượt xem: 2910 | Chuyên mục: Swift


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.
  1. 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.
  2. 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:
  1. GIFT: Tặng quà
  2. DISCOUNT: Giảm giá
  3. MONEY: Tặng tiền
  4. 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"

        }

    }

}
Bài tiếp theo: Struct trong swift >>
vncoder logo

Theo dõi VnCoder trên Facebook, để cập nhật những bài viết, tin tức và khoá học mới nhất!