ジェネリック関数の呼び出され方 #cocoa_kansai

111
EZ-NET 熊⾕友宏 http://ez-net.jp/ 2015.09.12 @ 第 63 回 Cocoa 勉強会関⻄ 呼び出され⽅を調べてみる ジェネリック関数の 『難しい』ことだけは分かった! !

Upload: tomohiro-kumagai

Post on 16-Apr-2017

929 views

Category:

Software


0 download

TRANSCRIPT

Page 1: ジェネリック関数の呼び出され方 #cocoa_kansai

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

2015.09.12 @ 第 63 回 Cocoa 勉強会関⻄

呼び出され⽅を調べてみるジェネリック関数の

『難しい』ことだけは分かった! !

Page 2: ジェネリック関数の呼び出され方 #cocoa_kansai

競合書、作ってます。

Xcode 5 徹底解説

VS

2014/04/28 -Xcode 5 完全攻略

2014/02/27 -

Page 3: ジェネリック関数の呼び出され方 #cocoa_kansai

競合書、作ってました。

Xcode 5 徹底解説

KO

2014/04/28 - 2015/08/21Xcode 5 完全攻略

2014/02/27 -

絶版!

Page 4: ジェネリック関数の呼び出され方 #cocoa_kansai

熊谷友宏EZ-NET http://ez-net.jp/ @es_kumagai

Xcode 5 徹底解説

IP Phone 音でダイヤル 音で再配達ゴッドいつもの電卓 with 割勘ウォッチ

MOSA

勉強会開催

#yidev 横浜 iPhone 開発者勉強会カジュアル Swift 勉強会 @ 青葉台

Page 5: ジェネリック関数の呼び出され方 #cocoa_kansai

Swift 2.0 GM

Page 6: ジェネリック関数の呼び出され方 #cocoa_kansai

Swift 2.0

▶ Protocol Extension ▶ Error Handling ▶ guard ▶ defer ▶ repeat-while ▶ pattern matching

新機能

▶ if-where ▶ for-where ▶ enum : String ▶ Type.init ▶ #available

Page 7: ジェネリック関数の呼び出され方 #cocoa_kansai

http://www.slideshare.net/tomohirokumagai54/swift-20-cswift

Swift 2.0新機能

Page 8: ジェネリック関数の呼び出され方 #cocoa_kansai

ジェネリックの活用の幅が広がったProtocol Extension

Page 9: ジェネリック関数の呼び出され方 #cocoa_kansai

http://www.slideshare.net/tomohirokumagai54/wwdc21cafe

Swift 2.0Protocol Extension

Page 10: ジェネリック関数の呼び出され方 #cocoa_kansai

extension CollectionType where Generator.Element : IntegerType {

var sum:Generator.Element { return self.reduce(0, combine: +) }

}

Protocol Extensionプロトコルに既定の実装を追加

Page 11: ジェネリック関数の呼び出され方 #cocoa_kansai

ジェネリックで条件を指定

extension CollectionType where Generator.Element : IntegerType {

Page 12: ジェネリック関数の呼び出され方 #cocoa_kansai

extension CollectionType where Generator.Element : IntegerType {

func action() -> String { return "A" } }

extension CollectionType where Generator.Element : BooleanType {

func action() -> String { return "B" } }

Array<Int>どちらの実装が採用される?

Page 13: ジェネリック関数の呼び出され方 #cocoa_kansai

extension CollectionType where Generator.Element : Equatable {

func action() -> String { return "A" } }

extension CollectionType where Generator.Element : Comparable {

func action() -> String { return "B" } }

Array<Int>どちらの実装が採用される?

Page 14: ジェネリック関数の呼び出され方 #cocoa_kansai

extension CollectionType where Generator.Element : Equatable {

func action() -> String { return "A" } }

extension CollectionType where Generator.Element : Hashable {

func action() -> String { return "B" } }

Array<Int>どちらの実装が採用される?

Page 15: ジェネリック関数の呼び出され方 #cocoa_kansai

extension CollectionType where Generator.Element : Comparable {

func action() -> String { return "A" } }

extension CollectionType where Generator.Element : ForwardIndexType {

func action() -> String { return "B" } }

Array<Int>どちらの実装が採用される?

Ambiguous

Page 16: ジェネリック関数の呼び出され方 #cocoa_kansai

ジェネリックの呼び出され方

Page 17: ジェネリック関数の呼び出され方 #cocoa_kansai

構造体と型指定

Page 18: ジェネリック関数の呼び出され方 #cocoa_kansai

シンプルな構造体 S1

struct S1 { }

Page 19: ジェネリック関数の呼び出され方 #cocoa_kansai

型の直指定

Page 20: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:S1) {

}

func f(v:S2) {

}

// 該当なし?

どの実装が採用される?シンプルな構造体 S1

Page 21: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:S1) {

}

func f(v:Any) {

}

// 該当なし?

どの実装が採用される?シンプルな構造体 S1

Page 22: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:S2) {

}

func f(v:Any) {

}

// 該当なし?

どの実装が採用される?シンプルな構造体 S1

Page 23: ジェネリック関数の呼び出され方 #cocoa_kansai

オプショナル

Page 24: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:S1) {

}

func f(v:S1?) {

}

// 該当なし?

どの実装が採用される?構造体とオプショナル S1?

Page 25: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:S1) {

}

func f(v:Any?) {

}

// 該当なし?

どの実装が採用される?構造体とオプショナル S1?

Page 26: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:S1) {

}

func f(v:Any) {

}

// 該当なし?

どの実装が採用される?構造体とオプショナル S1?

Page 27: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:Any) {

}

func f(v:Any?) {

}

// 該当なし?

どの実装が採用される?構造体とオプショナル S1?

※ 状況による

Page 28: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:Any) {

}

func f(v:Any?) {

}

どの実装が採用される?構造体とオプショナル S1?

• f(Optional(s1))

• let opt = Optional(s1) • f(opt) • or • f(Optional<S1>(s1))

Page 29: ジェネリック関数の呼び出され方 #cocoa_kansai

クラス

Page 30: ジェネリック関数の呼び出され方 #cocoa_kansai

シンプルなクラス A1

class A1 { }

Page 31: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:A1) {

}

func f(v:A2) {

}

// 該当なし?

どの実装が採用される?シンプルなクラス A1

Page 32: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:A1) {

}

func f(v:Any) {

}

// 該当なし?

どの実装が採用される?シンプルなクラス A1

Page 33: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:A2) {

}

func f(v:Any) {

}

// 該当なし?

どの実装が採用される?シンプルなクラス A1

Page 34: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:A1) {

}

func f(v:A1?) {

}

// 該当なし?

どの実装が採用される?クラスとオプショナル A1?

Page 35: ジェネリック関数の呼び出され方 #cocoa_kansai

クラス継承

Page 36: ジェネリック関数の呼び出され方 #cocoa_kansai

クラス継承

class A1 { }

class B1 : A1 { }

B1

A1

Page 37: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:B1) {

}

func f(v:B2) {

}

// 該当なし?

どの実装が採用される?クラス継承

B1

A1

Page 38: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:A1) {

}

func f(v:A2) {

}

// 該当なし?

どの実装が採用される?クラス継承

B1

A1

Page 39: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:A1) {

}

func f(v:B1) {

}

// 該当なし?

どの実装が採用される?クラス継承

B1

A1

Page 40: ジェネリック関数の呼び出され方 #cocoa_kansai

クラスを親で扱うとき

Page 41: ジェネリック関数の呼び出され方 #cocoa_kansai

let v:A1 = B1()

クラスを親で扱うときB1

A1

Page 42: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:A1) {

}

func f(v:A2) {

}

// 該当なし?

どの実装が採用される?クラスを親で扱うとき

B1

A1

Page 43: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:B1) {

}

func f(v:B2) {

}

// 該当なし?

どの実装が採用される?クラスを親で扱うとき

B1

A1

Page 44: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:A1) {

}

func f(v:B1) {

}

// 該当なし?

どの実装が採用される?クラスを親で扱うとき

B1

A1

Page 45: ジェネリック関数の呼び出され方 #cocoa_kansai

型指定とジェネリック指定

Page 46: ジェネリック関数の呼び出され方 #cocoa_kansai

基本的なジェネリック

Page 47: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:Any) {

}

型直指定で Anyおさらい S1

Page 48: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:Any) {

}

型直指定で Any型指定とジェネリック S1

func f<T>(v:T) {

}

func f<T:Any>(v:T) {

}

Page 49: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:Any) {

}

func f<T>(v:T) {

}

// 該当なし?

どの実装が採用される?型指定とジェネリック S1

Page 50: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T==S1>(v:T) {

}

// 該当なし?

どの実装が採用される?型指定とジェネリック S1

そもそも NG

Page 51: ジェネリック関数の呼び出され方 #cocoa_kansai

プロトコル

Page 52: ジェネリック関数の呼び出され方 #cocoa_kansai

構造体とプロトコル

protocol P1 { }

struct S1 : P1 { }

S1

P1

Page 53: ジェネリック関数の呼び出され方 #cocoa_kansai

プロトコルを型で扱う

Page 54: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:P1) {

}

// 該当なし?

どの実装が採用される?プロトコルを型で指定

S1

P1

Page 55: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:P1) {

}

func f(v:S1) {

}

// 該当なし?

どの実装が採用される?プロトコルを型で指定

S1

P1

Page 56: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:P1) {

}

func f(v:Any) {

}

// 該当なし?

どの実装が採用される?プロトコルを型で指定

S1

P1

Page 57: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:P2) {

}

func f(v:Any) {

}

// 該当なし?

どの実装が採用される?プロトコルを型で指定

S1

P1

Page 58: ジェネリック関数の呼び出され方 #cocoa_kansai

プロトコルをジェネリックで扱う

Page 59: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1>(v:T) {

}

// 該当なし?

どの実装が採用される?プロトコルを型で指定

S1

P1

Page 60: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1>(v:T) {

}

func f<T>(v:T) {

}

// 該当なし?

どの実装が採用される?プロトコルを型で指定

S1

P1

Page 61: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1>(v:T) {

}

func f<T>(v:T) {

}

func f(v:S1) {

}

どの実装が採用される?プロトコルを型で指定

S1

P1

Page 62: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1>(v:T) {

}

func f<T>(v:T) {

}

func f(v:P1) {

}

どの実装が採用される?プロトコルを型で指定

S1

P1

Page 63: ジェネリック関数の呼び出され方 #cocoa_kansai

複数のプロトコル

Page 64: ジェネリック関数の呼び出され方 #cocoa_kansai

複数のプロトコル

protocol P1 { }

protocol P2 { }

struct S1 : P1, P2 { }

S1

P1P2

Page 65: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:P1) {

}

func f(v:Any) {

}

// 該当なし?

どの実装が採用される?複数のプロトコル

S1

P1P2

Page 66: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:P2) {

}

func f(v:Any) {

}

// 該当なし?

どの実装が採用される?複数のプロトコル

S1

P1P2

Page 67: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:P1) {

}

func f(v:P2) {

}

func f(v:Any) {

}

どの実装が採用される?複数のプロトコル

S1

P1P2

Ambiguous

Page 68: ジェネリック関数の呼び出され方 #cocoa_kansai

func f(v:P1) {

}

func f(v:P2) {

}

func f(v:Any) {

}

どの実装が採用される?複数のプロトコル

S1

P1P2

• f(s1 as P1)

• f(s1 as P2)

Page 69: ジェネリック関数の呼び出され方 #cocoa_kansai

ジェネリックで複数プロトコル

Page 70: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1>(v:T) {

}

func f<T>(v:T) {

}

// 該当なし?

どの実装が採用される?複数のプロトコル

S1

P1P2

Page 71: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P2>(v:T) {

}

func f<T>(v:T) {

}

// 該当なし?

どの実装が採用される?複数のプロトコル

S1

P1P2

Page 72: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1>(v:T) {

}

func f<T:P2>(v:T) {

}

func f(v:Any) {

}

どの実装が採用される?複数のプロトコル

S1

P1P2

Ambiguous

Page 73: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1>(v:T) {

}

func f<T:P2>(v:T) {

}

func f<T>(v:T) {

}

どの実装が採用される?複数のプロトコル

• f(s1 as P1)

• f(s1 as P2)?

S1

P1P2

こうならない!

Page 74: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1>(v:T) {

}

func f<T:P2>(v:T) {

}

func f<T>(v:T) {

}

どの実装が採用される?複数のプロトコル

• f(s1 as P2)

• f(s1 as P1)

S1

P1P2

Page 75: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1>(v:T) {

}

func f<T:P2>(v:T) {

}

func f(v:Any) {

}

どの実装が採用される?複数のプロトコル

S1

P1P2

Page 76: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1>(v:T) {

}

func f<T:P2>(v:T) {

}

func f(v:Any) {

}

どの実装が採用される?複数のプロトコル

S1

P1P2

Page 77: ジェネリック関数の呼び出され方 #cocoa_kansai

プロトコル継承

Page 78: ジェネリック関数の呼び出され方 #cocoa_kansai

プロトコル継承

protocol P1 { }

protocol Q2 { }

protocol P2 : Q2 { }

struct S1 : P1, P2 { }

S1

P1P2

Q2

Page 79: ジェネリック関数の呼び出され方 #cocoa_kansai

ジェネリックで継承を扱う

Page 80: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1>(v:T) {

}

func f<T>(v:T) {

}

// 該当なし?

どの実装が採用される?プロトコル継承

S1

P1P2

Q2

Page 81: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P2>(v:T) {

}

func f<T>(v:T) {

}

// 該当なし?

どの実装が採用される?プロトコル継承

S1

P1P2

Q2

Page 82: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1>(v:T) {

}

func f<T:P2>(v:T) {

}

func f(v:Any) {

}

どの実装が採用される?プロトコル継承

S1

P1P2

Q2

Ambiguous

Page 83: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:Q2>(v:T) {

}

// 該当なし?

どの実装が採用される?プロトコル継承

S1

P1P2

Q2

Page 84: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:Q2>(v:T) {

}

func f<T:P2>(v:T) {

}

// 該当なし?

どの実装が採用される?プロトコル継承

S1

P1P2

Q2

Page 85: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1>(v:T) {

}

func f<T:Q2>(v:T) {

}

func f(v:Any) {

}

どの実装が採用される?プロトコル継承

S1

P1P2

Q2

Ambiguous

Page 86: ジェネリック関数の呼び出され方 #cocoa_kansai

じゃあ

クラスではどうなるのか …!

Page 87: ジェネリック関数の呼び出され方 #cocoa_kansai

プロトコル継承

protocol P1 protocol P2 : Q2 protocol Q2 protocol R1 : Q2

class C1 : C2, P1, P2 class C2 : P1, R1

C1

P1P2

Q2C2

P1R1

Q2

Page 88: ジェネリック関数の呼び出され方 #cocoa_kansai

クラス継承かつプロトコル継承

間に合いませんでした !

Page 89: ジェネリック関数の呼び出され方 #cocoa_kansai

じゃあ

複数引数ではどうなるのか …!

Page 90: ジェネリック関数の呼び出され方 #cocoa_kansai

複数引数の場合

間に合いませんでした ! !

Page 91: ジェネリック関数の呼び出され方 #cocoa_kansai

ひとつだけ

Page 92: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<A>(v1:A, v2:A) {

}

func f<A, B>(v1:A, v2:B) {

}

// 該当なし?

どの実装が採用される?複数条件での制約

P1

P1v1

v2

Page 93: ジェネリック関数の呼び出され方 #cocoa_kansai

じゃあ

プロトコル制約はどうなるのか …!

Page 94: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:CollectionType where Generator.Element:IntegerType>(v:T) {

}

func f<T:CollectionType where Generator.Element:BooleanType>(v:T) {

}

プロトコル制約想定する型の条件をプロトコルで指定

Page 95: ジェネリック関数の呼び出され方 #cocoa_kansai

where によるプロトコル制約

間に合いませんでした ! ! !

Page 96: ジェネリック関数の呼び出され方 #cocoa_kansai

じゃあ

複数の制約はどうなるのか …!

Page 97: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:CollectionType, U:Any where Generator.Element:ForwardIndexType, Generator:Element:Comparable> Generator:Element == U>(v:T, w:U) {

}

プロトコル制約想定する型の条件を複数指定

Page 98: ジェネリック関数の呼び出され方 #cocoa_kansai

複数条件でのプロトコル制約

間に合いませんでした ! ! ! !

Page 99: ジェネリック関数の呼び出され方 #cocoa_kansai

ひとつだけ

Page 100: ジェネリック関数の呼び出され方 #cocoa_kansai

プロトコルが子を内包

protocol P1

protocol P {

typealias PA typealias PB

var v1:PA {get} var v2:PB {get} }

P

PB

PA

class C1 : P1

class Base : P {

var v1:C1 var v2:C1 }

Page 101: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1, U:P1>(v1:T, v2:U) {

}

func f<T:Any, U:Any>(v1:T, v2:U) {

}

// 該当なし?

どの実装が採用される?複数条件での制約

P1

P1v1

v2

Page 102: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P1, U:P1>(v1:T, v2:U) {

}

func f<T:Any, U:Any>(v1:T, v2:U) {

}

// 該当なし?

どの実装が採用される?複数条件での制約

Q1

P1

P1

v1

v2

Page 103: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P

where T.PA:P1, T.PB:P1>(v:T) {

}

func f<T:P

where T.PA:Any, T.PB:Any>(v:T) {

}

どの実装が採用される?複数条件での制約 Base

P1

P1PA

PB

P

Page 104: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P

where T.PA:P1, T.PB:P1>(v:T) {

}

func f<T:P

where T.PA:Any, T.PB:Any>(v:T) {

}

どの実装が採用される?複数条件での制約 Base

Q1

P1

P1

PA

PB

P

Page 105: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P

where T.PA == T.PB>(v:T) {

}

func f<T:P

where T.PA:Any, T.PB:Any>(v:T) {

}

どの実装が採用される?複数条件での制約 Base

P1

P1PA

PB

P

Page 106: ジェネリック関数の呼び出され方 #cocoa_kansai

func f<T:P where T.PA:P1, T.PB:P1,

T.PA == T.PB>(v:T) {

}

func f<T:P

where T.PA:Any, T.PB:Any>(v:T) {

}

どの実装が採用される?複数条件での制約 Base

Q1

P1

P1

PA

PB

P

Page 107: ジェネリック関数の呼び出され方 #cocoa_kansai

じゃあ

プロトコル拡張はどうなるのか …!

Page 108: ジェネリック関数の呼び出され方 #cocoa_kansai

extension CollectionType where Generator.Element : IntegerType {

var sum:Generator.Element { return self.reduce(0, combine: +) }

}

プロトコル拡張プロトコルに既定の実装を追加

Page 109: ジェネリック関数の呼び出され方 #cocoa_kansai

プロトコル拡張

間に合いませんでした ! ! ! ! !

Page 110: ジェネリック関数の呼び出され方 #cocoa_kansai

とにかく混沌としている世界

構造体

クラス

クラス継承 プロトコル

プロトコル継承

型の直指定複数プロトコル

クラス継承とプロトコル

ジェネリックでの指定

型で縛る

プロトコル拡張

型の拡張

Page 111: ジェネリック関数の呼び出され方 #cocoa_kansai

統べるのは至難の業かもしれない

to be continued