112
EZ-NET 熊⾕友宏 http://ez-net.jp/ 2016.03.29 集まれSwift好き!Swift愛好会 #5 プロトコル指向に想う世界観 Swift カジュアルプログラミング Swift 2.2

プロトコル指向に想う世界観 #__swift__

Embed Size (px)

Citation preview

Page 1: プロトコル指向に想う世界観 #__swift__

EZ-NET 熊⾕友宏 http://ez-net.jp/

2016.03.29 集まれSwift好き!Swift愛好会 #5

プロトコル指向に想う世界観Swift カジュアルプログラミング

Swift 2.2

Page 2: プロトコル指向に想う世界観 #__swift__

熊谷友宏

Xcode 5 徹底解説 MOSA

Xcode 5 の全機能を徹底的に解説した本

OSX/iOS 系の歴史深い有料会員制の勉強会

紙版は絶版、電子書籍は販売中

Xcode 7 でも役立つはず 法人会員も多数

@es_kumagai EZ-NET http://ez-net.jp/

書籍 / 登壇

Page 3: プロトコル指向に想う世界観 #__swift__

熊谷友宏

横浜 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__

熊谷友宏@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__

CodePiece for OS X勉強会を楽しむアプリ

ソースコードを Twitter と Gist に同時投稿できる 勉強会で知見をみんなと共有したい時とかに便利!

できること

#__swift__

Page 6: プロトコル指向に想う世界観 #__swift__

プロトコル指向ってなんだろう

Page 7: プロトコル指向に想う世界観 #__swift__

プロトコル

プロトコル 拡張

型の拡張

▶ プロトコルは分かる。 ▶ プロトコル拡張って? ▶ 型に実装するのと違う? ▶ 型も拡張できるけど

何が違うの? ▶ プロトコル拡張って

ときどき変な動きする? ▶ 既定の実装に何か違和感 ▶ プロトコル拡張って

そもそも何?

プロトコル指向ってなんだろう使うほどに見えなくなる

Page 8: プロトコル指向に想う世界観 #__swift__

そこで

Page 9: プロトコル指向に想う世界観 #__swift__

スピリチュアル

Page 10: プロトコル指向に想う世界観 #__swift__

見えない世界からアプローチしたら見えなかった世界が見えてくる

… かも?

Page 11: プロトコル指向に想う世界観 #__swift__

あの世とこの世をつなぐもの

Page 12: プロトコル指向に想う世界観 #__swift__

プロトコルProtocol

Page 13: プロトコル指向に想う世界観 #__swift__

おさらい

Page 14: プロトコル指向に想う世界観 #__swift__

プロトコル

▶ 性質を決める ▶ 性質を表現するための概念を規定する

定義

protocol Movable { func moved(x x:Int, y:Int) -> Self func movedHorizontal(x:Int) -> Self func movedVertical(y:Int) -> Self

}

Page 15: プロトコル指向に想う世界観 #__swift__

プロトコル

▶ 概念を型で実現する … 実装 ▶ その性質を持つことが約束される

適用

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__

プロトコル

▶ 型は性質の通りに振る舞える ▶ 必ず、振る舞える

実現

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__

>> 概念だけで説明できるものに注目

Page 18: プロトコル指向に想う世界観 #__swift__

▶ プロトコルの概念だけで説明できる ▶ 適用する型ごとに変わるものではない

protocol Movable {

func moved(x x:Int, y:Int) -> Self

func movedHorizontal(x:Int) -> Self func movedVertical(y:Int) -> Self

}

プロトコル概念だけで説明できるもの

Page 19: プロトコル指向に想う世界観 #__swift__

プロトコル拡張

Page 20: プロトコル指向に想う世界観 #__swift__

▶ プロトコルの概念だけで説明する ▶ 既存の概念から新しい概念を作る … 実装?

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__

プロトコル拡張

▶ 最低限の概念を型に落とし込む ▶ プロトコル拡張で規定した概念が使える

型は最低限の概念だけを実現

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__

ジェネリック関数

Page 23: プロトコル指向に想う世界観 #__swift__

ジェネリック関数

▶ 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__

プロトコルの実例

Page 25: プロトコル指向に想う世界観 #__swift__

CollectionType複数の要素をまとめて扱う型の性質

Page 26: プロトコル指向に想う世界観 #__swift__

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__

// 要素の数を取得できる 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__

プロトコルは自作できる

Page 29: プロトコル指向に想う世界観 #__swift__

案外 むずかしいやってみると

Page 30: プロトコル指向に想う世界観 #__swift__

protocol PlayerType {

var content: Music? { get } var canPlay: Bool { get }

func play() throws }

プロトコル自作の難しさインターフェイスを規定する

Page 31: プロトコル指向に想う世界観 #__swift__

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__

let player = MusicPlayer(content: Music("SomeMusic.mp3"))

if player.canPlay { try player.play() }

プロトコル自作の難しさ型にプロトコルを適用したときの動き

ちゃんと動く

再生 !

Page 33: プロトコル指向に想う世界観 #__swift__

プロトコル自作の難しさ

プロトコル拡張を使うとき

Page 34: プロトコル指向に想う世界観 #__swift__

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__

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__

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__

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__

let player = MusicPlayer(content: Music("SomeMusic.mp3"))

if player.canPlay { try player.play() }

プロトコル自作の難しさプロトコル拡張で規定したときの動き

ちゃんと動く

再生 !

Page 39: プロトコル指向に想う世界観 #__swift__

プロトコル自作の難しさ

拡張とは別に独自実装するとき

Page 40: プロトコル指向に想う世界観 #__swift__

プロトコル自作の難しさ別の型では独自に実装する

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__

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__

// どんな 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__

プロトコル自作の難しさ

宣言しないで拡張できる…けれど

Page 44: プロトコル指向に想う世界観 #__swift__

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__

if player1.canPlay { try player1.play() }

if player2.canPlay { try player2.play() }

プロトコル自作の難しさcanPlay を宣言から省いたときの動き

再生 !

こちらは動きがおかしくなる…?

try start(player1) try start(player2)

こちらはちゃんと動く

再生 !

player1 は 再生される player2 は 再生されない

Page 46: プロトコル指向に想う世界観 #__swift__

プロトコル自作の難しさ

さらにプロトコル拡張で共通化を図る…

Page 47: プロトコル指向に想う世界観 #__swift__

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__

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__

こちらも動きがおかしくなる…?

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__

いったい何が起こっているのか

Page 51: プロトコル指向に想う世界観 #__swift__

見えない世界を垣間見たい何か得体の知れない世界

Page 52: プロトコル指向に想う世界観 #__swift__

得てして人が頼るものそんなときに

Page 53: プロトコル指向に想う世界観 #__swift__

スピリチュアル

Page 54: プロトコル指向に想う世界観 #__swift__

Swift の世界を観察スピリチュアルで

Page 55: プロトコル指向に想う世界観 #__swift__

プロトコル型

精神世界物質世界

人間界〓

霊界型に囚われない世界型の世界

Page 56: プロトコル指向に想う世界観 #__swift__

物質世界 精神世界

人間界 霊界

明確に分離

見える 見えない

人間 (インスタンス)

プロトコル型

Page 57: プロトコル指向に想う世界観 #__swift__

物質世界 精神世界

人間界 霊界

干渉する

人間 (インスタンス)

プロトコル型

魂 / 霊 (???) 霊媒

Page 58: プロトコル指向に想う世界観 #__swift__

Implementation を観察

Page 59: プロトコル指向に想う世界観 #__swift__

Implementation を観察型とプロトコルにおける実装

人間界 霊界

プロトコル型

Implementation Default Implementation

extension Human {

func speak() { … } }

extension Speakable {

func speak() { … } }

Page 60: プロトコル指向に想う世界観 #__swift__

Implementation を観察何に実装されるのかに着目

人間界 霊界

物質世界 精神世界

Implementation Default Implementation

func speak() func speak()

プロトコル型

“物体にしゃべり方を定義” … わかる気がする

“魂にしゃべり方を定義” … よくわからない

Page 61: プロトコル指向に想う世界観 #__swift__

Implementation を観察観測的な視点に着目

人間界 霊界

物質世界 精神世界

func speak() func speak()

見える 見えない

人間 (インスタンス)

Page 62: プロトコル指向に想う世界観 #__swift__

見えてくること

Page 63: プロトコル指向に想う世界観 #__swift__

プロトコル型

Implementation を観察ふたつの “同じ” 実装の 違い

人間界 霊界

func speak()

実体✓ 見える ✓ しゃべり方を知っているから しゃべれる

Page 64: プロトコル指向に想う世界観 #__swift__

プロトコル型

Implementation を観察ふたつの “同じ” 実装の 違い

人間界 霊界

func speak()

実体✓ 見えない ✓ なんかわからないけど しゃべれる

Page 65: プロトコル指向に想う世界観 #__swift__

なんかわからないけど 出来る

Page 66: プロトコル指向に想う世界観 #__swift__

プロトコルは

本能

Page 67: プロトコル指向に想う世界観 #__swift__

Implementation

人間界 霊界

プロトコル型

Implementation Default Implementation

func speak() func speak()

“物体にしゃべり方を搭載” … 後天的にできることを規定

“魂にしゃべり方を刻む”… 先天的にできることを規定

ふたつの “同じ” 実装の 意味合い

Page 68: プロトコル指向に想う世界観 #__swift__

2世界からのアプローチ

Page 69: プロトコル指向に想う世界観 #__swift__

2世界からのアプローチプロトコル拡張とは別に独自実装

▶ プロトコル拡張でメソッドを定義 ▶ 同じメソッドを型で独自に定義

// 型の定義 class Human : Speakable {

func speak() { …

} }

// プロトコルの定義 protocol Speakable {

}

extension Speakable {

func speak() { …

} }

Page 70: プロトコル指向に想う世界観 #__swift__

プロトコル型

2世界からのアプローチプロトコル拡張とは別に独自実装

人間界 霊界

func speak() func speak()

実体

こちらが実行される こちらは実行されない

型の実装で上書きされた?

Page 71: プロトコル指向に想う世界観 #__swift__

2世界からのアプローチそれぞれの世界に存在する

人間界 霊界

物質世界 精神世界

人間 (インスタンス)

func speak() func speak()

現実に存在している 見えないだけで存在している

見えるものを実行

魂 / 霊 (???)

本能を発現

本能は隠蔽される (言葉こそ意思疎通手段)

本能が解放される (言葉に依らない意思疎通)

Page 72: プロトコル指向に想う世界観 #__swift__

精神世界からの干渉

Page 73: プロトコル指向に想う世界観 #__swift__

歩く

Page 74: プロトコル指向に想う世界観 #__swift__

歩く

▶ 足を使って移動する行為

▶ 片足を地面について重心を乗せ、もう片足を進行方向へ運ぶ

概要

Page 75: プロトコル指向に想う世界観 #__swift__

地面はどこにあるのか

Page 76: プロトコル指向に想う世界観 #__swift__

歩く

▶ 地面は物質世界にある ▶ 歩く概念は精神世界にも存在できる ▶ 足を地につけられるのは現実世界だけ ▶ 精神世界だけでは実現できない

地面はどこにあるのか

精神世界が現実世界に干渉する必要性

Page 77: プロトコル指向に想う世界観 #__swift__

歩く

人間 (インスタンス)

魂 / 霊 (???)

霊媒

精神世界が現実世界に干渉

人間界 霊界

干渉する

物質世界 精神世界

プロトコル型

歩きを発現

歩行を念ずる

Page 78: プロトコル指向に想う世界観 #__swift__

干渉する事柄をプロトコルで規定

Page 79: プロトコル指向に想う世界観 #__swift__

歩く干渉する事柄をプロトコルで規定

▶ プロトコルで物質世界への干渉を宣言 ▶ 型で物質世界での動きを具現化

// 型の定義 class Human : Walkable {

func walk() { …

} }

// プロトコルの定義 protocol Walkable {

func walk() }

extension Walkable {

}

宣言

具現化

Page 80: プロトコル指向に想う世界観 #__swift__

歩く2世界からのアプローチ

人間界 霊界

物質世界 精神世界

人間 (インスタンス)

func walk() func walk()

実際の歩行を定義 概念のみを規定

見えるものを実行

魂 / 霊 (???)

歩行を念じる

現実に干渉

現実で体現

Page 81: プロトコル指向に想う世界観 #__swift__

先天性と後天性

Page 82: プロトコル指向に想う世界観 #__swift__

先天性と後天性要約

▶ プロトコル拡張で規定したものは 先天的 ▶ 型で規定したものは 後天的

// 人間には独自の遊泳を定義 class Human : Swimmable {

func swim() { …

} }

// 犬の遊泳は本能に従う class Dog : Swimmable {

}

// プロトコルの定義 protocol Swimmable {

func swim() }

extension Swimmable {

func swim() { …

} }

Page 83: プロトコル指向に想う世界観 #__swift__

先天性と後天性本能の発現

人間界 霊界

物質世界 精神世界

犬 (インスタンス)

func swim() { … }

なぜか泳げる

魂 / 霊 (???)

func swim()

現実に干渉

現実で体現

遊泳を念じる

本能が発現

Page 84: プロトコル指向に想う世界観 #__swift__

先天性と後天性体験による本能の置き換え

人間界 霊界

物質世界 精神世界

人間 (インスタンス)

func swim() { … }

泳ぎは習得した

魂 / 霊 (???)

func swim()

遊泳を念じる

本能は隠蔽

func swim()

現実に干渉

現実で体現

Page 85: プロトコル指向に想う世界観 #__swift__

型からの解放

Page 86: プロトコル指向に想う世界観 #__swift__

プロトコル型

型からの解放魂とは何者なのか

人間界 霊界

人間 (インスタンス)

func speak() func speak()

見えるものを実行

魂 / 霊 (???)

本能を発現

これは 何者なのか

Page 87: プロトコル指向に想う世界観 #__swift__

型からの解放

▶ プロトコルで引数の種類を特定する ▶ 実際の型に囚われない

ヒントは ジェネリック関数

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__

型に囚われない世界

精神世界

Page 89: プロトコル指向に想う世界観 #__swift__

型からの解放ジェネリックによる昇華

人間界 霊界

物質世界 精神世界

人間 (インスタンス)

func speak() func speak()

ジェネリックを通して霊体へと昇華

魂 / 霊 (???)

本能を発現

Page 90: プロトコル指向に想う世界観 #__swift__

型からの解放本能による昇華

人間界 霊界

物質世界 精神世界

人間 (インスタンス)

func speak() func speak()

本能を通して魂に昇華

魂 / 霊 (???)

本能を発現

func laugh()

なぜか笑える

Page 91: プロトコル指向に想う世界観 #__swift__

見えない世界を垣間見たいプロトコルの世界観

1. プロトコルは本能 2. 物質世界と精神世界、2つのアプローチ 3. 精神世界から物質世界への干渉を宣言 4. 先天性と後天性という実装観点 5. ジェネリックによる型からの解放

Page 92: プロトコル指向に想う世界観 #__swift__

これが …プロトコルの世界 … !?

Page 93: プロトコル指向に想う世界観 #__swift__

動作事例を解く

Page 94: プロトコル指向に想う世界観 #__swift__

プロトコル自作の難しさ

canPlay を宣言から省いたときの動き

Page 95: プロトコル指向に想う世界観 #__swift__

プロトコル自作の難しさ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__

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__

if player1.canPlay { try player1.play() }

if player2.canPlay { try player2.play() }

プロトコル自作の難しさcanPlay を宣言から省いたときの動き

再生 !

こちらは動きがおかしくなる…?

try start(player1) try start(player2)

こちらはちゃんと動く

再生 !

player1 は 再生される player2 は 再生されない

Page 98: プロトコル指向に想う世界観 #__swift__

プロトコル自作の難しさcanPlay を宣言から省いたときの動き

人間界 霊界

SilentSoundPlayer (インスタンス)

現実に存在している 見えないだけで存在している

canPlay を発動

魂 / 霊 (ジェネリック)

ジェネリック引数に渡す (型から解き放たれる)

本能が解放される (型に囚われない世界)

発現しない

プロトコル型

var canPlay() var canPlay

本能が発現

Page 99: プロトコル指向に想う世界観 #__swift__

プロトコル自作の難しさ

さらにプロトコル拡張で共通化を図る…

Page 100: プロトコル指向に想う世界観 #__swift__

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__

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__

こちらも動きがおかしくなる…?

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__

if player2.canPlay {

プロトコル自作の難しさplay をプロトコル拡張で共通化したときの動き

まずはこれから観察

Page 104: プロトコル指向に想う世界観 #__swift__

プロトコル自作の難しさplay をプロトコル拡張で共通化したときの動き

人間界 霊界

SilentSoundPlayer (インスタンス)

現実に存在している 見えないだけで存在している

発現しないプロトコル型

var canPlay() var canPlay

実装が発現

型から直接実行

見えるものを実行

Page 105: プロトコル指向に想う世界観 #__swift__

try player2.play()

プロトコル自作の難しさplay をプロトコル拡張で共通化したときの動き

そしてこれを観察

Page 106: プロトコル指向に想う世界観 #__swift__

プロトコル自作の難しさplay をプロトコル拡張で共通化したときの動き

人間界 霊界

SilentSoundPlayer (インスタンス)

見えないだけで存在している

本能が解放される (型に囚われない世界)

発現しない

プロトコル型

var canPlay() var canPlay

本能が発現

型から直接実行

なぜか play できる

var play

canPlay を発動

Page 107: プロトコル指向に想う世界観 #__swift__

プロトコルの挙動を説明できた!スピリチュアルで

Page 108: プロトコル指向に想う世界観 #__swift__

ほかにも

Page 109: プロトコル指向に想う世界観 #__swift__

プロトコル型

ほかにもデータの保存場所は物質世界

人間界 霊界

人間 (インスタンス)

var story:String

データの入れ物は物質世界に所属

魂 / 霊 (???)

読み書きするには 現実への干渉が不可欠

var story:String

Page 110: プロトコル指向に想う世界観 #__swift__

プロトコル型

ほかにもインスタンスは物質世界に生成

人間界 霊界

インスタンス (インスタンス)

init()

インスタンスは 物質世界に生成

魂 / 霊 (???)

インスタンス生成には 現実への干渉が不可欠

init()

Page 111: プロトコル指向に想う世界観 #__swift__

以上

プロトコル指向に想う世界観

Page 112: プロトコル指向に想う世界観 #__swift__

まとめプロトコル指向に想う世界観

1. プロトコル志向ってなんだろう ✓ プロトコル、ジェネリック関数、プロトコル拡張 ✓ 自作は案外難しい

2. 見えない世界を垣間見たい ✓ 2世界からのアプローチ ✓ 精神世界からの干渉

• 歩く、地面はどこにあるのか • 干渉する事柄をプロトコルで規定

✓ 先天性と後天性 ✓ 型からの解放

3. 動作事例を解く