Published on

Swift-da Enum-lardan qanday foydalanish kerak

Authors

Hammaga yana xush kelibsiz, mening ismim Nick, bu Swiftful Thinking va biz bu pleylist bo'ylab oldinga siljiyapmiz. O'tgan videoda struct-lar haqida o'rgandik β€” struct-lar nihoyatda muhim, ehtimol mening eng sevimli turm. Ammo bu videoda biz enum-larni ko'rib chiqamiz. Enum-lar xotirada qanday saqlanishi jihatidan struct-larga juda o'xshaydi, lekin bitta muhim farq bor: runtime'da biz enum'ning barcha case-larini yoki versiyalarini bilamiz. Struct'da esa runtime'da barcha case-larni bilishimiz shart emas.

Buning ma'nosini tushuntirish uchun oddiy misol keltiray. Tasavvur qiling, siz restoran ilovasi yasayapsiz va bu ilovada ko'plab oshxona turlari bor β€” italyan, yapon, amerikan taomi va hokazo. Endi bu ilovaning ikki versiyasini tasavvur qiling:

  • Birinchi versiya: Barcha ma'lumotlarni internetdan yuklab olamiz va keyin qaysi oshxona turlari borligini aniqlaymiz. Bu holda kodni yozayotganda qaysi oshxonalar bo'lishini bilmaymiz β€” shu sababli struct ishlatamiz.
  • Ikkinchi versiya: Kodni yozayotganda ilovadagi har bir oshxona turini allaqachon bilamiz β€” amerikan, yapon, italyan, grek va boshqalar. Bu holda enum ishlatamiz.

Agar enum ishlatish imkoniyati bo'lsa, uni struct'dan afzal ko'ramiz. Ammo ko'p hollarda faqat struct ishlatish mumkin bo'ladi.


Struct bilan muammo

Avval struct bilan boshlaylik:

struct CarModel {
    var brand: String
    var model: String
}

var car1 = CarModel(brand: "Ford", model: "Fiesta")
var car2 = CarModel(brand: "Ford", model: "Focus")
var car3 = CarModel(brand: "Toyota", model: "Camry")

Bu ishlaydi, lekin brand β€” bu oddiy String. Ya'ni, aslida faqat mashina brendlarini kiritsak ham, istagancha narsa kiritish mumkin:

var car1 = CarModel(brand: "Kofe", model: "Fiesta") // Bu ham ishlaydi!

Bu holda ma'lumotlar buzilishi yoki boshqa dasturchi xato ishlatishi mumkin. Shu muammoni hal qilish uchun brandni alohida struct sifatida ajratamiz:

struct CarBrand {
    var title: String
}

struct CarModel {
    var brand: CarBrand
    var model: String
}

var brand1 = CarBrand(title: "Ford")
var brand2 = CarBrand(title: "Toyota")

var car1 = CarModel(brand: brand1, model: "Fiesta")
var car2 = CarModel(brand: brand1, model: "Focus")
var car3 = CarModel(brand: brand2, model: "Camry")

Kod biroz yaxshilandi. Lekin hali ham istagancha string kiritish mumkin. Agar ilovamizda faqat Ford va Toyota bo'lishini bilsak, enum ishlatgan ma'qul.


Enum yaratish

enum CarBrandOption {
    case ford
    case toyota
    case honda
}

Yoki qisqaroq yozish mumkin:

enum CarBrandOption {
    case ford, toyota, honda
}

Endi CarModel struct'ida brand uchun CarBrandOption ishlatamiz:

struct CarModel {
    var brand: CarBrandOption
    var model: String
}

var car1 = CarModel(brand: .ford, model: "Fiesta")
var car2 = CarModel(brand: .ford, model: "Focus")
var car3 = CarModel(brand: .toyota, model: "Camry")

Endi kompilyator faqat .ford, .toyota yoki .honda kiritishga ruxsat beradi. "Kofe" yoki boshqa noto'g'ri qiymat kiritib bo'lmaydi β€” bu katta afzallik!


Enum va xotira

// Enum xotirada struct kabi saqlanadi (stack)
// Lekin muhim farq: enum mutatsiya qilinmaydi

enum CarBrandOption {
    case ford, toyota, honda
}

O'tgan videoda struct'ni qanday mutatsiya qilishni o'rgandik. CarBrandOption uchun esa mutatsiya yo'q β€” bu case-lar o'zgarmas. Ford doim Ford bo'lib qoladi, biz kodni yozayotganda uni o'zgartirishimiz mumkin emas.


Enum ichida computed variable

Enum'dan title olish uchun computed variable qo'shishimiz mumkin:

enum CarBrandOption {
    case ford, toyota, honda

    var title: String {
        if self == .ford {
            return "Ford"
        } else if self == .toyota {
            return "Toyota"
        } else {
            return "Default"
        }
    }
}

Bu ishlaydi, lekin if-else bilan muammo bor β€” bitta case-ni o'tkazib yuborishimiz mumkin. Masalan, .honda uchun default qiymat qaytariladi, bu noto'g'ri.


Switch statement bilan to'g'ri yondashuv

Enum bilan ishlashda switch statement eng yaxshi yondashuv hisoblanadi:

enum CarBrandOption {
    case ford, toyota, honda

    var title: String {
        switch self {
        case .ford:
            return "Ford"
        case .toyota:
            return "Toyota"
        case .honda:
            return "Honda"
        }
    }
}

switch statement'ning katta afzalligi β€” kompilyator barcha case-lar ko'rib chiqilganligini tekshiradi. Agar .honda case'ini yozsangiz va uni switch'da ko'rib chiqmasangiz, kompilyator xato beradi va ilovani ishga tushirishga ruxsat bermaydi. Bu "exhaustive switch" deb ataladi.


Default qiymat bilan switch

Agar barcha case-larni alohida ko'rib chiqmasangiz, default ishlatishingiz mumkin:

enum CarBrandOption {
    case ford, toyota, honda

    var title: String {
        switch self {
        case .ford:
            return "Ford"
        case .toyota:
            return "Toyota"
        default:
            return "Boshqa brend"
        }
    }
}

default ishlatish mumkin, lekin barcha case-larni alohida ko'rib chiqish yaxshiroq amaliyot hisoblanadi.


Enum'ni ishlatish

var fordBrand: CarBrandOption = .ford
print(fordBrand.title) // "Ford"

Enum ni qachon, Struct ni qachon ishlatish kerak?

HolatFoydalanish
Kodni yozayotganda barcha case-lar ma'lumenum
Case-lar ma'lumotlar bazasidan keladi yoki oldindan noma'lumstruct

Xulosa

Enum β€” bu barcha mumkin bo'lgan qiymatlarni oldindan belgilaydigan maxsus tur. Agar ilovangizda qiymatlar to'plami cheklangan va oldindan ma'lum bo'lsa, enum ishlatgan ma'qul. Bu kodingizni xavfsizroq va o'qilishi osonroq qiladi. Lekin qiymatlar dinamik bo'lsa yoki ma'lumotlar bazasidan kelsa, struct bilan ishlang.

Rahmat, men Nick, bu Swiftful Thinking va keyingi videoda ko'rishguncha!

Buy mea coffee