Protocol OptionSet

除了 Enum ,你還有 OptionSet 呀

OptionSet 和 Enum 很像,但又不太一樣 ( 廢話… (誤) )

OptionSet 協議:

A type that presents a mathematical set interface to a bit set.
一種透過不同位元組合表示不同選項的枚舉類型。

OptionSet 和 Enum 皆為枚舉類型:
Enum 為通用枚舉
OptionSet 則能存在多種元素組合

若變數行為像「單選題」可使用 Enum
多選題」則可選擇使用 OptionSet。

Let’s Code:

OptionSet 聯絡資訊 為例
聯絡資訊: 姓名電話信箱地址

struct Contact: OptionSet {
let rawValue: Int //⭐️required property
static let name = Contact( rawValue: 1 << 0 ) //0001
static let phone = Contact( rawValue: 1 << 1 ) //0010
static let email = Contact( rawValue: 1 << 2 ) //0100
static let address = Contact( rawValue: 1 << 3 ) //1000

static let mustHave: Contact = [ name, phone ]
static let all: Contact = [ name, phone, email, address ]
}
print(Contact.name) //Contact(rawValue: 1)
print(Contact.phone) //Contact(rawValue: 2)
print(Contact.email) //Contact(rawValue: 4)
print(Contact.address) //Contact(rawValue: 8)

使用 1 << 0 進行位元進位運算,透過不同 bit 表示不同選項。

OptionSet 能存在多種元素集合,分別組了兩組組合,必填欄位所有欄位

static let mustHave: Contact = [ name, phone ]
static let all: Contact = [ name, phone, email, address ]
print(Contact.mustHave) //Contact(rawValue: 3) = 1+2
print(Contact.all) //Contact(rawValue: 15) = 1+2+4+8

要注意的是每個 static properties 本質上還是一個「集合」的概念,就算只包含一個元素都是如此!

//以下皆為集合
var singleOption: Contact = .name
var mustHaveOptions: Contact = .mustHave
var contactOptions: Contact = [.name, .phone, .address]

Using an OptionSet:

let mustHave: Contact = [ name, phone ]
var
contactOptions: Contact = [.name, .phone, .address]
//兩個集合中相同的元素
let
intersection = contactOptions.intersection(mustHave)
print(intersection) //Contact(rawValue: 3) -> name,phone
//兩個集合的所有元素
let
union = contactOptions.union(mustHave)
print(union) //Contact(rawValue: 11) -> name,phone, address
//兩個集合未相同的元素
let
subtracting = contactOptions.subtracting(mustHave)
print(subtracting) //Contact(rawValue: 8) -> address
//Bool: A 是否包含 B 元素
let
contains = contactOptions.contains(mustHave)
print(contains) //true
//新增/刪除元素
contactOptions.insert(.email)
contactOptions.remove(.email)

Checking:

func checking() {
if contactOptions.contains(.name) {
print("name")
}
if contactOptions.contains(.mustHave) {
print("mustHave")
}
if contactOptions.contains(.all) {
print("all")
}
}
  • OptionSet 也可加入CaseIterable 使用 Contact.allCases

--

--