継承あまり使いたくないけど、同じメソッドを異なるクラスで使えるようにしたいことがある。
RubyではMixinという機能が提供されており、簡単に実現できる。
Swiftでも、Swift2.0で追加されたprotocol拡張を使うと、Mixinを実現できる。
protocolにextensionを作ってあげると、メソッドのデフォルト挙動を設定することができる。
protocol DogStyle {
func bow()
}
extension DogStyle {
func bow() {
print("bow wow!!")
}
}
class Human: DogStyle {
}
class Fish: DogStyle {
}
let kenji = Human()
kenji.bow() //"bow wow!!"
let iwana = Fish()
iwana.bow() //"bow wow!!"
上の例だと、DogStyle protocolをくっつけてやると、HumanもFishもbow()が使えるようになる。
インスタンス変数にアクセスするようなメソッドでも、protocolに変数の定義を書いてあげれば使えるようになる。
protocol DogStyle {
func bow()
}
extension DogStyle {
func bow() {
print("bow wow!!")
}
}
protocol CatStyle {
var times: Int { get set }
func meow()
}
extension CatStyle {
func meow() {
for _ in 0..<times {
print("mew meow!!")
}
}
}
class Human: DogStyle, CatStyle {
var times: Int
init(times: Int) {
self.times = times
}
}
class Fish: DogStyle, CatStyle {
var times: Int
init(times: Int) {
self.times = times
}
}
let kenji = Human(times: 5)
kenji.bow()
kenji.meow()
let iwana = Fish(times: 10)
iwana.bow()
iwana.meow()
上の例だと、CatStyle protocolのmeow()メソッドは、変数timesを参照している。
その場合も、protocol内で変数timesを定義してあげて、protocolに準拠するクラスの方でも用意してあげれば良い。
便利。