この投稿は何?
過去の投稿で、Swift標準ライブラリにある基本的なプロトコルをいくつか扱いました。
今回は、独自のプロトコルを定義して、準拠するまでを実践したいと思います。
実行環境
Xcode10.2.1
Swift5.x
ハンズオン
「フルーツを商品として扱う」みたいなケースを想定しています。
こんな型があったとして...
Fruit
型は果物を表現しています。
リンゴとオレンジをインスタンス生成しました。
struct Fruit {
var name: String
var emoji: String
var sugarContent: Int
}
// インスタンスを生成
let apple = Fruit(name: "Apple", emoji: "🍎", sugarContent: 8)
let orange = Fruit(name: "Orange", emoji: "🍊", sugarContent: 11)
商品として販売するには
この Fruit
型を商品として扱うには欠けている情報があります。
例えば、価格とかですね。
単純にメンバープロパティとして、price
を定義しても良さそうです。
ただ、商品として扱うのは Fruit
型オブジェクトだけとは限りません。
もしかしたら、ジュースとして Drink
型みたいなオブジェクトがあるかもしれません。
商品プロトコルを定義することにします。
そうすれば、商品として扱うなら価格が決まっていることが保証されますし、 price
プロパティの実装を忘れることはありません。
ついでに、宣伝メッセージを出力してくれるメソッドもあるといいですね。
protocol Salable {
var price: Int { get set }
func advertise()
}
プロトコルの定義では、具体的な値や実装はありません。
この時点で、金額が決まっていたり、宣伝文句を固定するのはおかしなハナシです。
また、プロパティは読み取り専用・読み書き可を明示する必要があります。
プロトコルに準拠する
Salable
プロトコルを採用すると、エラーメッセージが表示されます。
Type 'Fruit' does not conform to protocol 'Salable'
Fixボタンを押すと、準拠に必要なプロパティおよびメソッドが自動的に記述されます。
struct Fruit: Salable {
var name: String
var emoji: String
var sugarContent: Int
var price: Int
func advertise() {
print("This \(name) is ¥\(price)")
}
}
advertise
メソッドは、この時点で具体的な実装を記述します。
プロトコルを採用した型次第で、実装をアレンジできます。
インスタンスを生成する
すでに生成したインスタンスはプロパティに初期値がないから、エラーになります。
初期化コードを修正します。
let apple = Fruit(name: "Apple", emoji: "🍎", sugarContent: 8, price: 100)
let orange = Fruit(name: "Orange", emoji: "🍊", sugarContent: 11, price: 120)
プロトコルに準拠して、販売可能になったことを確認しましょう。
apple.advertise() // This Apple is ¥100
orange.advertise() // This Orange is ¥120
メッセージが出力されました。
Protocol-Oriented Programming
クラスには継承という概念がありますが、構造体に継承はありません。
一方で、Swiftプログラミングではクラスより構造体を使うことが推奨されているようです。
プロパティやメソッドの共用をプロトコルで設計することが POP の基本と感じました。