Enum’lar, birbiri ile alakalı değerleri gruplamamızı sağlayan yapılardır. Basit örneklerden başlarsak; haftanın günleri, cinsiyetler, takas(alım-satım) gibi içerisinde birden fazla değer barındıran fakat temelde bir çatıya ait olan yapıları nitelendirirler. Value type olarak çalışırlar.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
enum Days { case Monday case Tuesday case Wednesday case Thursday case Friday case Saturday case Sunday } enum Days { case Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } |
Yukarıdaki gibi iki farklı şekilde de ifade edilebilirler.
rawValue
Enum’lara bir tip vererek ardından istediğimiz her bir case için de bu tipi karşılamasını sağlayarak rawValue oluşturabiliriz.
1 2 3 4 5 6 |
enum Days: String { case Monday = "Very first day of week.", Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } print(Days.Monday.rawValue) |
Örneğin yukarıdaki gibi Pazartesi günü için bir rawValue tanımı yaparsak aşağıdaki gibi bir sonuç alacağızdır.
Peki rawValue değeri yalnızca bu şekilde bir String göstermek gibi basit bir şey için mi kullanılacaktır. Tabii ki hayır.
Şimdi backend’den bize bazı bilgilerin enum olarak değil de belirli stringler ile geldiğini düşünelim. Fakat bunlar bizim için bir çatıyı oluşturan farklı durumlar olsun. Benim vereceğim örnekte vergiler üzerinden gideceğiz. Client tarafında kendimiz bir Enum oluşturalım ve String rawValue’a sahip olsun. Ardından backend’den geleceğine emin olduğumuz, el sıkışılan durumlar için case’leri oluşturalım ve her ihtimale karşı bir tane de “other” case’i oluşturalım.
Son olarak Enum’a ait bir static fonksiyon oluşturarak “init(rawValue:)” metodu ile bir case’ini oluşturup bize döndürmesini sağlayalım. “init(rawValue:)” metodu geriye optional döndüğü için böyle bir metot oluşturmak istedim. “init(rawValue:)” bir case oluşturamadan bize dönerse de “other” case’i döndürmesini isteyelim.
1 2 3 4 5 6 7 8 9 10 |
enum Tax: String { case income = "INCOME" case vehicle = "VEHICLE" case insurance = "INSURANCE" case other static func getTax(with rawValue: String) -> Tax { return Tax.init(rawValue: rawValue) ?? Tax.other } } |
Daha sonrasında da iki farklı case oluşturarak sonuçları görelim.
1 2 3 4 5 6 |
var income = Tax.getTax(with: "INCOME") print(income.rawValue) var dummy = Tax.getTax(with: "dummy") print(dummy.rawValue) |
Geçerli bir rawValue ile oluşturmaya çalıştığım zaman istediğim sonucu bana verdi. Fakat geçersiz bir rawValue ile gittiğim zaman da “other” case’i bana döndürmeyi başardı.
Eğer Int türünde bir rawValue’a sahip olmak istersek ve hiçbir rawValue değerini biz vermezsek, 0’dan başlayarak artırımlı olarak tüm case’lere ait rawValue’ları verecektir.
1 2 3 4 5 6 7 8 |
enum NumberSystem: Int { case two, eight, nine, ten } print(NumberSystem.two.rawValue) print(NumberSystem.eight.rawValue) print(NumberSystem.nine.rawValue) print(NumberSystem.ten.rawValue) |
Yani yukarıdaki koddan aşağıdaki gibi bir çıktı alacağız.
Fakat örneğin biz bir tanesine rawValue değeri verdik ve kalanlara yine bir dokunuşta bulunmadıysak, verilen case’den sonraki case’lerin rawValue’ları o case’in rawValue’sunu takiben artırımlı olarak devam edecektir.
1 2 3 4 5 6 7 8 |
enum NumberSystem: Int { case two = 2, eight = 3, nine, ten } print(NumberSystem.two.rawValue) print(NumberSystem.eight.rawValue) print(NumberSystem.nine.rawValue) print(NumberSystem.ten.rawValue) |
CustomStringConvertible
Oluşturduğumuz enum’ın bir Int tipi rawValue’su olmasını istiyor ve aynı zamanda da anlamlı bir “String” tanım vermek istiyorsak “CustomStringConvertible” protokolüne uymasını sağlayabiliriz.
Örneğin aşağıdaki örnekte haftanın günlerine Pazartesiden itibaren 1,2…,7 olacak şekilde rawValue verdik. Aynı zamanda bir extension yazarak “CustomStringConvertible” protokolüne uydurduk ve hafta içi ve hafta sonu için özel tanımlarını yaptık.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
extension Days: CustomStringConvertible { var description: String { switch self { case .Sunday, .Saturday: return "Weekend" default: return "Weekday" } } } print(Days.Monday) print(Days.Monday.rawValue) |
Peki şimdiye kadar sürekli bir case’in oluşturulması yönünü inceledik. Şimdi de biraz elimizde oluşmuş case’e ait işlemleri nasıl yaparız sorusuna cevap arayalım.
switch-case
Elimizde bir case var ise bunu bir switch-case kontrolü ile kullanabiliriz.
1 2 3 4 5 6 7 8 9 10 11 12 |
enum Days { case Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } var sunday = Days.Sunday switch sunday { case .Sunday: print("Last day before work, enjoy it.") default: print("") } |
Yukarıdaki kod parçasında pazar gününe özel bir mesaj vermek istiyoruz ve aşağıdaki gibi bir sonuç alıyoruz.
if case
switch-case kullanımı dışında “if-case” kullanarak da çözüm arayabiliriz. Genel olarak çok fazla case var ise ve küçük bir kısmına yönelik çalışmak istiyorsam bunu tercih ediyorum.
1 2 3 4 5 6 7 |
var sunday = Days.Sunday if case .Monday = sunday { print("Hafta başlıyor.") } else { print("Hafta çoktan başladı.") } |
Enum with Associated values
Enum’lar içerisinde bulunan her bir case kullanılacağı yere kendisiyle beraber bazı değerler de götürebilir. Örneğin bir vergi türünü kontrol ederken aynı zamanda miktarına da bakmak istediğimizi düşünelim. Bu durumda case içerisinde “Double”, “Int” farketmez nasıl bir kurgu yapıyorsak, miktar değerini de götürür.
1 2 3 4 5 6 |
enum Tax { case income(amount: Double) case vehicle(horsepower: Double) case insurance(policyName: String) case other } |
Ardından elde edilen bir gelir vergisi oluşturup, tutar değerimizi nasıl gönderiyoruz görelim.
1 2 3 4 5 6 7 |
let incomeTax = Tax.income(amount: 900) switch incomeTax { case .income(let amount): print(amount) default: break } |
Kod parçasının sonucu olarak da yukarıdaki gibi bir çıktı elde edeceğiz.