この記事は何?
前回は、Equatable
プロトコルを扱いました。
今回は、続きとも言える Comparable
プロトコルです。
実行環境
Xcode10.2.1
Swift5.x
ハンズオン
Playground で動作確認しました。
こんな型があったとして
フルーツを表現する Fruit
型です。
3つのプロパティ name
, emoji
, sugarContent
があります。
struct Fruit {
var name: String
var emoji: String
var sugarContent: Int // フルーツの甘さ(糖度)
}
let apple = Fruit(name: "Apple", emoji: "🍎", sugarContent: 15)
let banana = Fruit(name: "Banana", emoji: "🍌", sugarContent: 10)
let cherry = Fruit(name: "Cherry", emoji: "🍒", sugarContent: 3)
なお、実際の各種フルーツとその糖度と比較して、上記コードの値がどうかは知りません。
配列 fruits
に並べてみましょう。
let fruits = [apple, banana, cherry] // [🍎, 🍌, 🍒]
甘いフルーツ(つまり、糖度が高い)順に並べ替えらるようにします。
小さいかどうか、大きいかどうか
「どっちが大きいか」は、逆にいうと「小さいかどうか」ってこと。
<
演算子です。
「小さいかどうか」が調べらることを保証するのが Comparable
プロトコルです。
Comparable
プロトコルに準拠していないオブジェクトの大小関係を比較すると...
apple < banana
Comparable の要件
Comparable
プロトコルに準拠するには、2つの要件を満たす必要があります。
-
Equatable
であること -
<
メソッドを実装していること
1.Equatableに準拠させる
1つ目の要件を満たすため、型を Equatable
にします。
詳しくは前回の投稿を。
struct Fruit: Equatable {
var name: String
var emoji: String
var sugarContent: Int
static func == (lhs: Fruit, rhs: Fruit) -> Bool {
return lhs.emoji == rhs.emoji
}
}
2. < メソッドを実装する
プロトコルを列挙したら、<
静的メソッドを実装します。
このメソッド内で、「何を基準に大小関係を判断するか」を定義します。
Fruit
型では糖度を表現する sugarContent
の値で大小比較することにします。
struct Fruit: Equatable, Comparable {
var name: String
var emoji: String
var sugarContent: Int
static func == (lhs: Fruit, rhs: Fruit) -> Bool {
return lhs.emoji == rhs.emoji
}
// 小さいかどうかをBoolで返す
static func < (lhs: Fruit, rhs: Fruit) -> Bool {
return lhs.sugarContent < rhs.sugarContent
}
}
糖度を比較する
もう一度、apple
が banana
より小さいかどうかを比較します。
apple < banana // true
apple.sugarContent
は 5
で、banana.sugarContent
は 10
なので true
が得られるようになりました。
大きいかどうかの演算子 >
はどうでしょうか?
apple > banana // false
>
メソッドは実装していませんが、自動的に呼び出せるようになっています。
配列をソートする
それでは、糖度が高い順に fruits
配列をソートします。
Array
型に用意されている sorted(by:)
メソッドを使いましょう。
print( fruits.sorted(by: >) ) // [🍒, 🍌, 🍎]
コンソールには [🍒, 🍌, 🍎]
が出力されます。
(CustomStringConvertible
プロトコル準拠が前提です。こちらで解説。)
糖度が高い順に並べ替えができました。