プロトコル指向に想う世界観 #__swift__
TRANSCRIPT
![Page 1: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/1.jpg)
EZ-NET 熊⾕友宏 http://ez-net.jp/
2016.03.29 集まれSwift好き!Swift愛好会 #5
プロトコル指向に想う世界観Swift カジュアルプログラミング
Swift 2.2
![Page 2: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/2.jpg)
熊谷友宏
Xcode 5 徹底解説 MOSA
Xcode 5 の全機能を徹底的に解説した本
OSX/iOS 系の歴史深い有料会員制の勉強会
紙版は絶版、電子書籍は販売中
Xcode 7 でも役立つはず 法人会員も多数
@es_kumagai EZ-NET http://ez-net.jp/
書籍 / 登壇
![Page 3: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/3.jpg)
熊谷友宏
横浜 iPhone 開発者勉強会#yidev
わいわい・ゆるく、iPhone 開発者のみんなで楽しく過ごすのが目的の会
【 横浜・馬車道 】カジュアル Swift 勉強会
#cswift
ゆるくみんなで Swift を語らえる場を作りたくて始めた会
【 横浜・青葉台 】
第23回を 2016-05-07 に開催予定 第6回を 2016-04-02 に開催
@es_kumagai EZ-NET http://ez-net.jp/
勉強会
![Page 4: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/4.jpg)
熊谷友宏@es_kumagai EZ-NET http://ez-net.jp/
CodePiece
iOS, OS X, Apple Watch アプリ
ソースコードを Twitter と Gist に同時投稿できる。
いつもの電卓計算式も見える電卓アプリ。 watchOS 1 対応
音で再配達ゴッド簡単操作で 再配達の申し込み。
EZ-NET IP PhoneiPhone でひかり電話を使う。 自宅 LAN からの利用専用
![Page 5: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/5.jpg)
CodePiece for OS X勉強会を楽しむアプリ
ソースコードを Twitter と Gist に同時投稿できる 勉強会で知見をみんなと共有したい時とかに便利!
できること
#__swift__
![Page 6: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/6.jpg)
プロトコル指向ってなんだろう
![Page 7: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/7.jpg)
プロトコル
プロトコル 拡張
型
型の拡張
▶ プロトコルは分かる。 ▶ プロトコル拡張って? ▶ 型に実装するのと違う? ▶ 型も拡張できるけど
何が違うの? ▶ プロトコル拡張って
ときどき変な動きする? ▶ 既定の実装に何か違和感 ▶ プロトコル拡張って
そもそも何?
プロトコル指向ってなんだろう使うほどに見えなくなる
![Page 8: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/8.jpg)
そこで
![Page 9: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/9.jpg)
スピリチュアル
![Page 10: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/10.jpg)
見えない世界からアプローチしたら見えなかった世界が見えてくる
… かも?
![Page 11: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/11.jpg)
あの世とこの世をつなぐもの
![Page 12: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/12.jpg)
プロトコルProtocol
![Page 13: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/13.jpg)
おさらい
![Page 14: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/14.jpg)
プロトコル
▶ 性質を決める ▶ 性質を表現するための概念を規定する
定義
protocol Movable { func moved(x x:Int, y:Int) -> Self func movedHorizontal(x:Int) -> Self func movedVertical(y:Int) -> Self
}
![Page 15: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/15.jpg)
プロトコル
▶ 概念を型で実現する … 実装 ▶ その性質を持つことが約束される
適用
struct Location : Movable { func moved(x x:Int, y:Int) -> Location {
return movedHorizontal(x).movedVertical(y) } func movedHorizontal(x:Int) -> Location {
return Location(x: self.x + x, y: self.y) } func movedVertical(y:Int) -> Location {
return Location(x: self.x, y: self.y + y) }
}
![Page 16: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/16.jpg)
プロトコル
▶ 型は性質の通りに振る舞える ▶ 必ず、振る舞える
実現
var location = Location(x: 0, y: 0)
location = location.movedHorizontal(10) location = location.movedVertical(20) location = location.moved(x: 4, y: 8)
![Page 17: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/17.jpg)
>> 概念だけで説明できるものに注目
![Page 18: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/18.jpg)
▶ プロトコルの概念だけで説明できる ▶ 適用する型ごとに変わるものではない
protocol Movable {
func moved(x x:Int, y:Int) -> Self
func movedHorizontal(x:Int) -> Self func movedVertical(y:Int) -> Self
}
プロトコル概念だけで説明できるもの
![Page 19: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/19.jpg)
プロトコル拡張
![Page 20: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/20.jpg)
▶ プロトコルの概念だけで説明する ▶ 既存の概念から新しい概念を作る … 実装?
protocol Movable { func moved(x x:Int, y:Int) -> Self func movedHorizontal(x:Int) -> Self func movedVertical(y:Int) -> Self
}
extension Movable { func moved(x x:Int, y:Int) -> Self {
return movedHorizontal(x).movedVertical(y) }
}
プロトコル拡張新概念を作る
![Page 21: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/21.jpg)
プロトコル拡張
▶ 最低限の概念を型に落とし込む ▶ プロトコル拡張で規定した概念が使える
型は最低限の概念だけを実現
struct Location : Movable { func movedHorizontal(x:Int) -> Location {
return Location(x: self.x + x, y: self.y) } func movedVertical(y:Int) -> Location {
return Location(x: self.x, y: self.y + y) }
}
// 既定の実装が使える let location = Location().moved(x: 10, y: 10)
![Page 22: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/22.jpg)
ジェネリック関数
![Page 23: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/23.jpg)
ジェネリック関数
▶ Movable に対応する型、みたいに指定 ▶ プロトコルで規定した性質だけで組み立てる
任意の型を受け取れる関数
func randomMove<T:Movable>(location: T, maxStep: Int) -> T { let deltaX = Int(arc4random_uniform(UInt32(maxStep))) let deltaY = Int(arc4random_uniform(UInt32(maxStep))) return location.moved(x: deltaX, y: deltaY) }
// Movable に対応した Location 型を渡せる var location = Location(x: 0, y: 0)
location = randomMove(location, maxStep: 100)
![Page 24: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/24.jpg)
プロトコルの実例
![Page 25: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/25.jpg)
CollectionType複数の要素をまとめて扱う型の性質
![Page 26: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/26.jpg)
extension Location : CollectionType { var startIndex: Int { return 0 } var endIndex: Int { return 2 } subscript (index: Int) -> Int { switch index { case 0: return x case 1: return y default: fatalError() } } }
CollectionType型に適用
![Page 27: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/27.jpg)
// 要素の数を取得できる location.count
// 最初の要素 (x) と最後の要素 (y) を取得できる location.first! location.last!
// 要素を順次処理 (x -> y) できる for v in location { }
// すべての要素 (x, y) をそれぞれ 2 倍にした配列を取得する location.map { $0 * 2 }
// x, y で、小さい方の値や大きい方の値を取得できる location.minElement() location.maxElement()
CollectionType配列のように振る舞う型になる
![Page 28: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/28.jpg)
プロトコルは自作できる
![Page 29: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/29.jpg)
案外 むずかしいやってみると
![Page 30: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/30.jpg)
protocol PlayerType {
var content: Music? { get } var canPlay: Bool { get }
func play() throws }
プロトコル自作の難しさインターフェイスを規定する
![Page 31: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/31.jpg)
final class MusicPlayer : PlayerType { var content: Music? var canPlay: Bool { return content != nil } func play() throws { guard canPlay else { throw PlayerError.NotReady } try AVAudioPlayer(data: content!.data).play() } }
プロトコル自作の難しさ型にプロトコルを適用する
![Page 32: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/32.jpg)
let player = MusicPlayer(content: Music("SomeMusic.mp3"))
if player.canPlay { try player.play() }
プロトコル自作の難しさ型にプロトコルを適用したときの動き
ちゃんと動く
再生 !
![Page 33: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/33.jpg)
プロトコル自作の難しさ
プロトコル拡張を使うとき
![Page 34: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/34.jpg)
final class MusicPlayer : PlayerType { var content: Music? var canPlay: Bool { return content != nil } func play() throws { guard canPlay else { throw PlayerError.NotReady } try AVAudioPlayer(data: content!.data).play() } }
プロトコル自作の難しさプロトコルの概念だけで作られた部分
型に依存しない
![Page 35: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/35.jpg)
extension PlayerType {
var canPlay: Bool { return content != nil } }
final class MusicPlayer : PlayerType {
var content: Music?
func play() throws {
guard canPlay else { throw PlayerError.NotReady } try AVAudioPlayer(data: content!.data).play() } }
プロトコル自作の難しさプロトコル拡張で規定する
プロトコル拡張 に移行
![Page 36: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/36.jpg)
final class MusicPlayer : PlayerType { var content: Music? func play() throws { guard canPlay else { throw PlayerError.NotReady } try AVAudioPlayer(data: content!.data).play() }
}
プロトコル自作の難しさプロトコルの概念だけで作られた部分
型に依存しない
![Page 37: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/37.jpg)
extension PlayerType { var canPlay: Bool { return content != nil }
func play() throws { guard canPlay else { throw PlayerError.NotReady } try AVAudioPlayer(data: content!.data).play() } }
final class MusicPlayer : PlayerType { var content: Music? }
プロトコル自作の難しさプロトコル拡張で規定する
プロトコル拡張 に移行
![Page 38: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/38.jpg)
let player = MusicPlayer(content: Music("SomeMusic.mp3"))
if player.canPlay { try player.play() }
プロトコル自作の難しさプロトコル拡張で規定したときの動き
ちゃんと動く
再生 !
![Page 39: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/39.jpg)
プロトコル自作の難しさ
拡張とは別に独自実装するとき
![Page 40: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/40.jpg)
プロトコル自作の難しさ別の型では独自に実装する
final class SilentSoundPlayer : PlayerType { let content: Music? = nil var canPlay: Bool { return true } func play() throws { guard canPlay else { throw PlayerError.NotReady } try AVAudioPlayer(data: NullSound().data).play() } }
![Page 41: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/41.jpg)
let player1 = MusicPlayer(content: Music("SomeMusic.mp3")) let player2 = SilentSoundPlayer()
if player1.canPlay { try player1.play() }
if player2.canPlay { try player2.play() }
プロトコル自作の難しさ別の型では独自に実装したときの動き
それぞれ期待通りに動く
再生 !
再生 !
![Page 42: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/42.jpg)
// どんな PlayerType にも対応した再生関数を用意 func start<T:PlayerType>(player: T) throws { if player.canPlay { try player.play() } }
// 用意した関数で再生する let player1 = MusicPlayer(content: Music("SomeMusic.mp3")) let player2 = SilentSoundPlayer()
try start(player1) try start(player2)
プロトコル自作の難しさ別の型では独自に実装したときの動き
ジェネリック関数で共通化してみる
どちらも 再生 !
![Page 43: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/43.jpg)
プロトコル自作の難しさ
宣言しないで拡張できる…けれど
![Page 44: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/44.jpg)
protocol PlayerType {
var content: Music? { get } // var canPlay: Bool { get }
func play() throws }
extension PlayerType { var canPlay: Bool { return content != nil }
func play() throws { guard canPlay else { throw PlayerError.NotReady } try AVAudioPlayer(data: content!.data).play() } }
プロトコルから 宣言を消去
![Page 45: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/45.jpg)
if player1.canPlay { try player1.play() }
if player2.canPlay { try player2.play() }
プロトコル自作の難しさcanPlay を宣言から省いたときの動き
再生 !
こちらは動きがおかしくなる…?
try start(player1) try start(player2)
こちらはちゃんと動く
再生 !
player1 は 再生される player2 は 再生されない
![Page 46: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/46.jpg)
プロトコル自作の難しさ
さらにプロトコル拡張で共通化を図る…
![Page 47: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/47.jpg)
protocol PlayerType {
var content: Music? { get } // var canPlay: Bool { get }
func play() throws }
extension PlayerType { var canPlay: Bool { return content != nil }
func play() throws { guard canPlay else { throw PlayerError.NotReady }
let data = content?.data ?? NullSound().data try AVAudioPlayer(data: data).play() } }
content = nil 時の 無音再生に対応
![Page 48: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/48.jpg)
final class SilentSoundPlayer : PlayerType { let content: Music? = nil var canPlay: Bool { return true } // func play() throws { // // guard canPlay else { // throw PlayerError.NotReady // } // // try AVAudioPlayer(data: NullSound().data).play() // } }
プロトコル拡張で 対応したので消去
![Page 49: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/49.jpg)
こちらも動きがおかしくなる…?
if player1.canPlay { try player1.play() }
if player2.canPlay { try player2.play() }
プロトコル自作の難しさplay をプロトコル拡張で共通化したときの動き
再生 !
こちらの動きは従前通りのおかしさ
try start(player1) try start(player2) player1 は 再生される
player2 は 再生されない
canPlay は 成功 play 実行時に NotReady エラー
![Page 50: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/50.jpg)
いったい何が起こっているのか
![Page 51: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/51.jpg)
見えない世界を垣間見たい何か得体の知れない世界
![Page 52: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/52.jpg)
得てして人が頼るものそんなときに
![Page 53: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/53.jpg)
スピリチュアル
![Page 54: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/54.jpg)
Swift の世界を観察スピリチュアルで
![Page 55: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/55.jpg)
プロトコル型
精神世界物質世界
〓
人間界〓
霊界型に囚われない世界型の世界
![Page 56: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/56.jpg)
物質世界 精神世界
人間界 霊界
明確に分離
見える 見えない
人間 (インスタンス)
プロトコル型
![Page 57: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/57.jpg)
物質世界 精神世界
人間界 霊界
干渉する
人間 (インスタンス)
プロトコル型
魂 / 霊 (???) 霊媒
![Page 58: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/58.jpg)
Implementation を観察
![Page 59: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/59.jpg)
Implementation を観察型とプロトコルにおける実装
人間界 霊界
プロトコル型
Implementation Default Implementation
extension Human {
func speak() { … } }
extension Speakable {
func speak() { … } }
![Page 60: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/60.jpg)
Implementation を観察何に実装されるのかに着目
人間界 霊界
物質世界 精神世界
Implementation Default Implementation
func speak() func speak()
プロトコル型
“物体にしゃべり方を定義” … わかる気がする
“魂にしゃべり方を定義” … よくわからない
![Page 61: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/61.jpg)
Implementation を観察観測的な視点に着目
人間界 霊界
物質世界 精神世界
func speak() func speak()
見える 見えない
人間 (インスタンス)
![Page 62: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/62.jpg)
見えてくること
![Page 63: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/63.jpg)
プロトコル型
Implementation を観察ふたつの “同じ” 実装の 違い
人間界 霊界
func speak()
実体✓ 見える ✓ しゃべり方を知っているから しゃべれる
![Page 64: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/64.jpg)
プロトコル型
Implementation を観察ふたつの “同じ” 実装の 違い
人間界 霊界
func speak()
実体✓ 見えない ✓ なんかわからないけど しゃべれる
![Page 65: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/65.jpg)
なんかわからないけど 出来る
![Page 66: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/66.jpg)
プロトコルは
本能
![Page 67: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/67.jpg)
Implementation
人間界 霊界
プロトコル型
Implementation Default Implementation
func speak() func speak()
“物体にしゃべり方を搭載” … 後天的にできることを規定
“魂にしゃべり方を刻む”… 先天的にできることを規定
ふたつの “同じ” 実装の 意味合い
![Page 68: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/68.jpg)
2世界からのアプローチ
![Page 69: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/69.jpg)
2世界からのアプローチプロトコル拡張とは別に独自実装
▶ プロトコル拡張でメソッドを定義 ▶ 同じメソッドを型で独自に定義
// 型の定義 class Human : Speakable {
func speak() { …
} }
// プロトコルの定義 protocol Speakable {
}
extension Speakable {
func speak() { …
} }
![Page 70: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/70.jpg)
プロトコル型
2世界からのアプローチプロトコル拡張とは別に独自実装
人間界 霊界
func speak() func speak()
実体
こちらが実行される こちらは実行されない
型の実装で上書きされた?
![Page 71: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/71.jpg)
2世界からのアプローチそれぞれの世界に存在する
人間界 霊界
物質世界 精神世界
人間 (インスタンス)
func speak() func speak()
現実に存在している 見えないだけで存在している
見えるものを実行
魂 / 霊 (???)
本能を発現
本能は隠蔽される (言葉こそ意思疎通手段)
本能が解放される (言葉に依らない意思疎通)
![Page 72: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/72.jpg)
精神世界からの干渉
![Page 73: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/73.jpg)
歩く
![Page 74: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/74.jpg)
歩く
▶ 足を使って移動する行為
▶ 片足を地面について重心を乗せ、もう片足を進行方向へ運ぶ
概要
![Page 75: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/75.jpg)
地面はどこにあるのか
![Page 76: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/76.jpg)
歩く
▶ 地面は物質世界にある ▶ 歩く概念は精神世界にも存在できる ▶ 足を地につけられるのは現実世界だけ ▶ 精神世界だけでは実現できない
地面はどこにあるのか
精神世界が現実世界に干渉する必要性
![Page 77: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/77.jpg)
歩く
人間 (インスタンス)
魂 / 霊 (???)
霊媒
精神世界が現実世界に干渉
人間界 霊界
干渉する
物質世界 精神世界
プロトコル型
歩きを発現
歩行を念ずる
![Page 78: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/78.jpg)
干渉する事柄をプロトコルで規定
![Page 79: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/79.jpg)
歩く干渉する事柄をプロトコルで規定
▶ プロトコルで物質世界への干渉を宣言 ▶ 型で物質世界での動きを具現化
// 型の定義 class Human : Walkable {
func walk() { …
} }
// プロトコルの定義 protocol Walkable {
func walk() }
extension Walkable {
}
宣言
具現化
![Page 80: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/80.jpg)
歩く2世界からのアプローチ
人間界 霊界
物質世界 精神世界
人間 (インスタンス)
func walk() func walk()
実際の歩行を定義 概念のみを規定
見えるものを実行
魂 / 霊 (???)
歩行を念じる
現実に干渉
現実で体現
![Page 81: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/81.jpg)
先天性と後天性
![Page 82: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/82.jpg)
先天性と後天性要約
▶ プロトコル拡張で規定したものは 先天的 ▶ 型で規定したものは 後天的
// 人間には独自の遊泳を定義 class Human : Swimmable {
func swim() { …
} }
// 犬の遊泳は本能に従う class Dog : Swimmable {
}
// プロトコルの定義 protocol Swimmable {
func swim() }
extension Swimmable {
func swim() { …
} }
![Page 83: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/83.jpg)
先天性と後天性本能の発現
人間界 霊界
物質世界 精神世界
犬 (インスタンス)
func swim() { … }
なぜか泳げる
魂 / 霊 (???)
func swim()
現実に干渉
現実で体現
遊泳を念じる
本能が発現
![Page 84: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/84.jpg)
先天性と後天性体験による本能の置き換え
人間界 霊界
物質世界 精神世界
人間 (インスタンス)
func swim() { … }
泳ぎは習得した
魂 / 霊 (???)
func swim()
遊泳を念じる
本能は隠蔽
func swim()
現実に干渉
現実で体現
![Page 85: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/85.jpg)
型からの解放
![Page 86: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/86.jpg)
プロトコル型
型からの解放魂とは何者なのか
人間界 霊界
人間 (インスタンス)
func speak() func speak()
見えるものを実行
魂 / 霊 (???)
本能を発現
これは 何者なのか
![Page 87: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/87.jpg)
型からの解放
▶ プロトコルで引数の種類を特定する ▶ 実際の型に囚われない
ヒントは ジェネリック関数
func randomMove<T:Movable>(location: T, maxStep: Int) -> T { … }
// Movable に対応した Location 型を渡せる var location = Location(x: 0, y: 0)
location = randomMove(location, maxStep: 100)
![Page 88: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/88.jpg)
型に囚われない世界
精神世界
![Page 89: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/89.jpg)
型からの解放ジェネリックによる昇華
人間界 霊界
物質世界 精神世界
人間 (インスタンス)
func speak() func speak()
ジェネリックを通して霊体へと昇華
魂 / 霊 (???)
本能を発現
![Page 90: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/90.jpg)
型からの解放本能による昇華
人間界 霊界
物質世界 精神世界
人間 (インスタンス)
func speak() func speak()
本能を通して魂に昇華
魂 / 霊 (???)
本能を発現
func laugh()
なぜか笑える
![Page 91: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/91.jpg)
見えない世界を垣間見たいプロトコルの世界観
1. プロトコルは本能 2. 物質世界と精神世界、2つのアプローチ 3. 精神世界から物質世界への干渉を宣言 4. 先天性と後天性という実装観点 5. ジェネリックによる型からの解放
![Page 92: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/92.jpg)
これが …プロトコルの世界 … !?
![Page 93: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/93.jpg)
動作事例を解く
![Page 94: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/94.jpg)
プロトコル自作の難しさ
canPlay を宣言から省いたときの動き
![Page 95: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/95.jpg)
プロトコル自作の難しさcanPlay を宣言から省いたときの動き
// このうちの player2 で不思議な動作が起こる let player1 = MusicPlayer(content: Music("SomeMusic.mp3")) let player2 = SilentSoundPlayer()
// どんな PlayerType にも対応した再生関数を用意 func start<T:PlayerType>(player: T) throws {
if player.canPlay {
try player.play() } }
ジェネリック引数は 型に囚われない
精神世界に解き放たれる〓
![Page 96: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/96.jpg)
protocol PlayerType {
var content: Music? { get } // var canPlay: Bool { get }
func play() throws }
extension PlayerType { var canPlay: Bool { return content != nil }
func play() throws { guard canPlay else { throw PlayerError.NotReady } try AVAudioPlayer(data: content!.data).play() } }
プロトコルから 宣言を消去
物質世界に干渉しない
〓
![Page 97: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/97.jpg)
if player1.canPlay { try player1.play() }
if player2.canPlay { try player2.play() }
プロトコル自作の難しさcanPlay を宣言から省いたときの動き
再生 !
こちらは動きがおかしくなる…?
try start(player1) try start(player2)
こちらはちゃんと動く
再生 !
player1 は 再生される player2 は 再生されない
![Page 98: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/98.jpg)
プロトコル自作の難しさcanPlay を宣言から省いたときの動き
人間界 霊界
SilentSoundPlayer (インスタンス)
現実に存在している 見えないだけで存在している
canPlay を発動
魂 / 霊 (ジェネリック)
ジェネリック引数に渡す (型から解き放たれる)
本能が解放される (型に囚われない世界)
発現しない
プロトコル型
var canPlay() var canPlay
本能が発現
![Page 99: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/99.jpg)
プロトコル自作の難しさ
さらにプロトコル拡張で共通化を図る…
![Page 100: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/100.jpg)
protocol PlayerType {
var content: Music? { get } // var canPlay: Bool { get }
func play() throws }
extension PlayerType { var canPlay: Bool { return content != nil }
func play() throws { guard canPlay else { throw PlayerError.NotReady }
let data = content?.data ?? NullSound().data try AVAudioPlayer(data: data).play() } }
content = nil 時の 無音再生に対応
本能側を調整
〓
プロトコルに 宣言しない
物質世界に干渉しない
〓
![Page 101: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/101.jpg)
final class SilentSoundPlayer : PlayerType { let content: Music? = nil var canPlay: Bool { return true } // func play() throws { // // guard canPlay else { // throw PlayerError.NotReady // } // // try AVAudioPlayer(data: NullSound().data).play() // } }
プロトコル拡張で 対応したので消去
本能に委ねる
〓
![Page 102: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/102.jpg)
こちらも動きがおかしくなる…?
if player1.canPlay { try player1.play() }
if player2.canPlay { try player2.play() }
プロトコル自作の難しさplay をプロトコル拡張で共通化したときの動き
再生 !
こちらの動きは従前通りのおかしさ
try start(player1) try start(player2) player1 は 再生される
player2 は 再生されない
canPlay は 成功 play 実行時に NotReady エラー
![Page 103: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/103.jpg)
if player2.canPlay {
プロトコル自作の難しさplay をプロトコル拡張で共通化したときの動き
まずはこれから観察
![Page 104: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/104.jpg)
プロトコル自作の難しさplay をプロトコル拡張で共通化したときの動き
人間界 霊界
SilentSoundPlayer (インスタンス)
現実に存在している 見えないだけで存在している
発現しないプロトコル型
var canPlay() var canPlay
実装が発現
型から直接実行
見えるものを実行
![Page 105: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/105.jpg)
try player2.play()
プロトコル自作の難しさplay をプロトコル拡張で共通化したときの動き
そしてこれを観察
![Page 106: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/106.jpg)
プロトコル自作の難しさplay をプロトコル拡張で共通化したときの動き
人間界 霊界
SilentSoundPlayer (インスタンス)
見えないだけで存在している
本能が解放される (型に囚われない世界)
発現しない
プロトコル型
var canPlay() var canPlay
本能が発現
型から直接実行
なぜか play できる
var play
canPlay を発動
![Page 107: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/107.jpg)
プロトコルの挙動を説明できた!スピリチュアルで
![Page 108: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/108.jpg)
ほかにも
![Page 109: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/109.jpg)
プロトコル型
ほかにもデータの保存場所は物質世界
人間界 霊界
人間 (インスタンス)
var story:String
データの入れ物は物質世界に所属
魂 / 霊 (???)
読み書きするには 現実への干渉が不可欠
var story:String
![Page 110: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/110.jpg)
プロトコル型
ほかにもインスタンスは物質世界に生成
人間界 霊界
インスタンス (インスタンス)
init()
インスタンスは 物質世界に生成
魂 / 霊 (???)
インスタンス生成には 現実への干渉が不可欠
init()
![Page 111: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/111.jpg)
以上
プロトコル指向に想う世界観
![Page 112: プロトコル指向に想う世界観 #__swift__](https://reader030.vdocuments.pub/reader030/viewer/2022021422/587123ea1a28abe4448b5b0b/html5/thumbnails/112.jpg)
まとめプロトコル指向に想う世界観
1. プロトコル志向ってなんだろう ✓ プロトコル、ジェネリック関数、プロトコル拡張 ✓ 自作は案外難しい
2. 見えない世界を垣間見たい ✓ 2世界からのアプローチ ✓ 精神世界からの干渉
• 歩く、地面はどこにあるのか • 干渉する事柄をプロトコルで規定
✓ 先天性と後天性 ✓ 型からの解放
3. 動作事例を解く