2014年11月22日
Posted by 屋台ブルー at
2014年11月22日00:00 Comment(0)
Swiftで遊ぼう! - 134 - プロトコールとデリゲーション 2
2015年8月18日追記:プロトコールとデリゲーション関連を調べていてこのページにいらしたSwift言語の初心者の皆さま、ここの内容は私が理解できていなかった頃に書いた記事なので注意して下さい。この後紆余曲折してプロトコールとデリゲーションの関係性は理解しました。その解説は次のリンクを見て下さい。
Swiftで遊ぼう! - 260 - プロトコールとデリゲーション ProtocolsとDelegation
-----ここから過去の記事
昨日の話に表題のプロトコールもデリゲーションも出てこなかった。プロトコールの説明をする前にクラスの継承の概念を復習したんですよね。
さて、プロトコール、一般的にインターフェイスと呼ばれるように、様々なクラスに共通の部品(属性)を持たせるための方法だ。よく考えると、共通の部品ということは、継承関係のある親クラスもプロトコール的な働きをしているとも言えるだろう。
じゃあプロトコールとスーパークラスの相違点は? 当然プログラマーな人達には当たり前のことですが、私のような初心者にはその概念の違いが最初わかりませんでした。プロトコールはポリモーフィズムを実現させるための道具です。もっとも重要な概念は継承されるクラスに囚われないということですよね。異なるクラスをまたいで共通部分を持たせることができるということですね。
じゃあプロトコールの実例としてコードを説明しよう。
@objc protocol Speaker {
func speak() -> String
optional func tellSomething() -> String
}
/* プロトコール宣言部分、ちょっと一般的な説明と違うのが、オプショナルなメソッドがプロパティに含まれているので、プロトコール宣言の頭に「@objc」をつけるのは決まり事として覚えておこう。 */
class Genki: Speaker {
func speak() -> String {
return "I'm Genki Tai"
}
}
/* プロトコールの実装のやり方が、スーパークラスの継承と似ているのは、やはり使い方が似ているからなんでしょうね。私のような初心者にとってやっかいなのが、このコードだけでSpeakerがスーパークラスなのかプロトコールなのか判断できませんよね。*/
class Yuki: Speaker {
func speak() -> String {
return "I'm Yuki Tai"
}
}
class Tomoko: Speaker {
func speak() -> String {
return "I'm Tomoko Tai"
}
func tellSomething() -> String {
return "Hey I'm kidding!"
}
}
class Satsuki: Speaker {
func speak() -> String {
return "I'm Satsuki Tai"
}
func tellSomething() -> String {
return "Hey what is booboo!"
}
func babyTalk() -> String {
return "Babooo Babooo"
}
}
/* 上記に4つの独立したクラスがあり、プロトコールSpeakerを使って共通したメソッドを持たせたということです。当然ですがメソッドの振る舞いは変えられる。しかし、プロトコールの醍醐味は、拡張性というより制限である。この制限という考え方を前面に出して説明しているところが少ないので初心者がプロトコールを勉強する時に分かりにくいんだと思う。プロトコールってのは、全く理解できていないフレームワークで構築されたAPI群の塊の一部を利用する時に使用される。利用する方が、プロトコールの内容だけに注意すればいいわけで、これを実際のインスタンス生成で説明する。*/
var tomoko = Tomoko()
tomoko.speak()
tomoko.tellSomething()
/* 上記のようにTomokoクラスでインスタンスを生成してやると、Tomokoクラスの内容をすべて知る必要があり、Tomokoクラスのプロパティは自由にアクセスできる。*/
var satsuki = Satsuki()
satsuki.babyTalk()
/* Satsukiクラスでインスタンス生成した時も同じで、すべてのプロパティにアクセスできる。しかし、プロトコールの利用法で重要なのは以下のような制限を加えたインスタンス生成じゃなかろうか。*/
var speaker: Speaker
speaker = Satsuki()
/* 実は、今回プロトコールの復習をしていて目から鱗だったのがプロトコールを使って変数宣言をしているところだ。まさに昨日話題にした親クラスで変数宣言して子クラスを生成するやり方。そのやり方をプロトコールでできるんですね。The Swift Programming Language本に記載されているのだろうか?読み落としていたというか、これって滅茶重要ですよね。*/
speaker.speak()
speaker.babyTalk() // しばり(制限)が入っているので当然エラーです。プロトコールで宣言している内容にしかアクセスできないんです。
/* さて、私が一番驚いたのは上記のことですが、オプショナルなメソッドの取り扱い方も説明しておこう。まだどういう時にこれを利用したらいいのか分からないんですけどね(^_^;) */
speaker.tellSomething() // こうしてやるとエラーになります。オプショナルな取り扱いはSwift独自機能のようですが、以下のようにしなければなりません。
speaker.tellSomething!() // 強制アンラップです。もし何もコードされていないとランタイムエラーになります。
speaker.tellSomething?() // これはオプショナルなままの扱いなので、何もコードされていなかったらnilを返し、何かコードされていたら「!」を使ってアンラップして使用しなければなりません。
今日はここまで。
Swiftで遊ぼう! - 260 - プロトコールとデリゲーション ProtocolsとDelegation
-----ここから過去の記事
昨日の話に表題のプロトコールもデリゲーションも出てこなかった。プロトコールの説明をする前にクラスの継承の概念を復習したんですよね。
さて、プロトコール、一般的にインターフェイスと呼ばれるように、様々なクラスに共通の部品(属性)を持たせるための方法だ。よく考えると、共通の部品ということは、継承関係のある親クラスもプロトコール的な働きをしているとも言えるだろう。
じゃあプロトコールとスーパークラスの相違点は? 当然プログラマーな人達には当たり前のことですが、私のような初心者にはその概念の違いが最初わかりませんでした。プロトコールはポリモーフィズムを実現させるための道具です。もっとも重要な概念は継承されるクラスに囚われないということですよね。異なるクラスをまたいで共通部分を持たせることができるということですね。
じゃあプロトコールの実例としてコードを説明しよう。
@objc protocol Speaker {
func speak() -> String
optional func tellSomething() -> String
}
/* プロトコール宣言部分、ちょっと一般的な説明と違うのが、オプショナルなメソッドがプロパティに含まれているので、プロトコール宣言の頭に「@objc」をつけるのは決まり事として覚えておこう。 */
class Genki: Speaker {
func speak() -> String {
return "I'm Genki Tai"
}
}
/* プロトコールの実装のやり方が、スーパークラスの継承と似ているのは、やはり使い方が似ているからなんでしょうね。私のような初心者にとってやっかいなのが、このコードだけでSpeakerがスーパークラスなのかプロトコールなのか判断できませんよね。*/
class Yuki: Speaker {
func speak() -> String {
return "I'm Yuki Tai"
}
}
class Tomoko: Speaker {
func speak() -> String {
return "I'm Tomoko Tai"
}
func tellSomething() -> String {
return "Hey I'm kidding!"
}
}
class Satsuki: Speaker {
func speak() -> String {
return "I'm Satsuki Tai"
}
func tellSomething() -> String {
return "Hey what is booboo!"
}
func babyTalk() -> String {
return "Babooo Babooo"
}
}
/* 上記に4つの独立したクラスがあり、プロトコールSpeakerを使って共通したメソッドを持たせたということです。当然ですがメソッドの振る舞いは変えられる。しかし、プロトコールの醍醐味は、拡張性というより制限である。この制限という考え方を前面に出して説明しているところが少ないので初心者がプロトコールを勉強する時に分かりにくいんだと思う。プロトコールってのは、全く理解できていないフレームワークで構築されたAPI群の塊の一部を利用する時に使用される。利用する方が、プロトコールの内容だけに注意すればいいわけで、これを実際のインスタンス生成で説明する。*/
var tomoko = Tomoko()
tomoko.speak()
tomoko.tellSomething()
/* 上記のようにTomokoクラスでインスタンスを生成してやると、Tomokoクラスの内容をすべて知る必要があり、Tomokoクラスのプロパティは自由にアクセスできる。*/
var satsuki = Satsuki()
satsuki.babyTalk()
/* Satsukiクラスでインスタンス生成した時も同じで、すべてのプロパティにアクセスできる。しかし、プロトコールの利用法で重要なのは以下のような制限を加えたインスタンス生成じゃなかろうか。*/
var speaker: Speaker
speaker = Satsuki()
/* 実は、今回プロトコールの復習をしていて目から鱗だったのがプロトコールを使って変数宣言をしているところだ。まさに昨日話題にした親クラスで変数宣言して子クラスを生成するやり方。そのやり方をプロトコールでできるんですね。The Swift Programming Language本に記載されているのだろうか?読み落としていたというか、これって滅茶重要ですよね。*/
speaker.speak()
speaker.babyTalk() // しばり(制限)が入っているので当然エラーです。プロトコールで宣言している内容にしかアクセスできないんです。
/* さて、私が一番驚いたのは上記のことですが、オプショナルなメソッドの取り扱い方も説明しておこう。まだどういう時にこれを利用したらいいのか分からないんですけどね(^_^;) */
speaker.tellSomething() // こうしてやるとエラーになります。オプショナルな取り扱いはSwift独自機能のようですが、以下のようにしなければなりません。
speaker.tellSomething!() // 強制アンラップです。もし何もコードされていないとランタイムエラーになります。
speaker.tellSomething?() // これはオプショナルなままの扱いなので、何もコードされていなかったらnilを返し、何かコードされていたら「!」を使ってアンラップして使用しなければなりません。
今日はここまで。