#この記事について
THE SWIFT PROGRAMMING LANGUAGE SWIFT5.5を参考・引用しております。
間違っていたら指摘お願いします。
enumの基礎編
書き方①
enum CompassPoint {
case north
case south
case east
case west
}
var directionToHead = CompassPoint.west
directionToHead = .east
enum(列挙型)は、関連する値のグループに共通の型を定義し、コード内で型安全な方法でこれらの値を扱うことができます。
上記の例で言うと、
north
,south
,east
,west
の値をCompassPoint
という任意の共通の型で定義し、グループ化しています。
それにより、
CompassPoint.west
という書き方ができるようになります。
私は、「CompassPointグループのwest君」みたいな覚え方をしております。
var directionToHead = CompassPoint.west
変数にenumで定義した型の値を代入すると、変数はその型を覚えてくれます。
directionToHead = .east
それにより、次に同じ型の値を代入する際は、省略した書き方をすることができます。
書き方②
enum Planet {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune //1行で表示もできる
}
「enumの書き方①」では、1つのcaseに1つの値を設定していましたが、実は1つのcaseに複数の値を設定することができます。
enumの応用篇
switchとenumで値をマッチングさせる
directionToHead = .south
switch directionToHead {
case .north:
print("Lots of planets have a north")
case .south:
print("Watch out for penguins")
case .east:
print("Where the sun rises")
case .west:
print("Where the skies are blue")
default:
print("Not a safe place for humans")
}
switchとenumを組み合わせることで、enumの値に合わせて処理を実行することができます。
値がない場合は、default
内の処理が実行されます。
enumにCaseIterableプロトコルを実装し、値をプロパティーとして扱う
enum Beverage: CaseIterable {
case coffee,tea,juice
}
let numberOfChoices = Beverage.allCases.count
print("\(numberOfChoices) beverages available")
for beverage in Beverage.allCases {
print(beverage)
}
上記では、enumにCaseIterable
プロトコルを実装させ、caseの値をプロパティーとして扱えるようにしています。
プロパティーと扱えることにより、
allCases.count
でcaseの数を数えたり、
for beverage in Beverage.allCases
で、caseの値をループで出力できるようになります。
enumに代入した値を再利用
enum Barcode {
case upc(Int,Int,Int,Int)
case qrCode(String)
}
var productBarcode = Barcode.upc(8, 85909,51226,3)
switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case .qrCode(let productCode):
print("QR code: \(productCode).")
}
case upc(Int,Int,Int,Int)
case qrCode(String)
enumのcaseでは上記の書き方ができます。
これは、各caseの値の型を定義しております。
「Barcodeグループのupc君がint型の値を4つ保持できる」と覚えると良いでしょう
var productBarcode = Barcode.upc(8, 85909,51226,3)
上記のように値を代入することができます。
enum、定義済みのcase、switchを使うことで、
enumに代入した値をswitchのcaseの処理内で再利用することができます。
enum応用篇②
生の値を定義
//明示的に生の値を定義する
enum ASCIIControlCharcter: Character {
case tab = "\t"
case lineFeed = "\n"
case carriageReturn = "\r"
}
//暗黙的に生の値を定義する
enum PlanetA: Int {
case mercury = 1, venus, earth, mars,jupiter,saturn,uranus, neptune
//venusは2になる。
//earthは3になる
}
ややこしいですが、enum(列挙型)は、関連する値のグループに共通の型を定義する以外にも他のことができます。
それは、「生の値」を定義することです。
上記の例だとCharacter型を使って
値にtab
を、
生の値に"\t"
を定義しています。
Int型を使えば、暗黙的に生の値を定義することができます。
「生の値」を定義する際には、他のcaseの生の値も全て同じ型である必要があります。
let positionToFind = 11
if let somePlanet = PlanetA(rawValue: positionToFind) { //オプショナルを外している
switch somePlanet {
case .earth:
print("Mostly harmless")
default:
print("Not a safe place for humans")
}
} else {
print("There isn't a planet at position \(positionToFind)")
}
値と生の値の関係性について、
連想配列のキーと値の関係性に似ているような感じがします。
rawValue
で生の値を定義することで、値を引っ張り出すことができます。ただし、オプショナル型なのでif let
などでアンラップする必要があります。
再帰的なenum
enum ArithmeticExpression {
case number(Int)
indirect case addtion(ArithmeticExpression,ArithmeticExpression)
indirect case multiplication(ArithmeticExpression,ArithmeticExpression)
}
再帰的な列挙(enum)とは、1つ以上の列挙ケースの関連する値として、その列挙の別のインスタンスを持つ列挙のことです。列挙ケースの前に indirect と書くことで、再帰的であることを示し、コンパイラに必要なインダイレクトの層を挿入するように指示します。
indirect enum ArithmeticExpressionA {
case number(Int)//普通の数字
case addition(ArithmeticExpressionA, ArithmeticExpressionA) //加算
case multiplication(ArithmeticExpressionA, ArithmeticExpressionA) //乗算
}
enumの前にindirectを書くことで、すべてのcaseが再帰的であると明示することができます。
//ArithmeticExpressionAの値を再帰的に利用する
let five = ArithmeticExpressionA.number(5)
let four = ArithmeticExpressionA.number(4)
let sum = ArithmeticExpressionA.addition(five, four)
let product = ArithmeticExpressionA.multiplication(sum, ArithmeticExpressionA.number(2))
// switchで値をアンラップする
func evaluate(_ expression: ArithmeticExpression) -> Int {
switch expression {
case let .number(value):
return value
case let .addition(left, right):
return evaluate(left) + evaluate(right)
case let .multiplication(left, right):
return evaluate(left) * evaluate(right)
}
}
print(evaluate(product))
// Prints "18"
上記の処理だと、
変数sum
が同じenumであるfive
とfour
を持っています。
さらに、変数product
は、同じenumであるsum
とArithmeticExpressionA.number(2)
を持っています。
このように、enumが同じenumを持つことを再帰的なenumと呼ばれています。