swift2 の新機能 protocol extension

73
Swift 2 の新機能 Protocol Extension 1 安達 勇一 クラスメソッド株式会社 2015年06月19日 Ⓒ Classmethod, Inc. #cmdevio

Upload: yuichi-adachi

Post on 31-Jul-2015

242 views

Category:

Engineering


14 download

TRANSCRIPT

Swift 2 の新機能 Protocol Extension

1

安達 勇一 クラスメソッド株式会社2015年06月19日

Ⓒ Classmethod, Inc.

#cmdevio

2

安達 勇一• 2013/12 入社

• TwitterID:   @UsrNameu1

• Github:    https://github.com/UsrNameu1

• Blog:    http://dev.classmethod.jp/author/yad

•        で連載やってます

Topics for today

• Protocol Extensionとは

• Protocol Extension詳細

• 標準APIの変更

3Ⓒ Classmethod, Inc.

Topics for today

• Protocol Extensionとは

• Protocol Extension詳細

• 標準APIの変更

4Ⓒ Classmethod, Inc.

Protocol Extensionとは• Protocolのおさらい

• Extensionのおさらい

• Protocol Extensionとは

5Ⓒ Classmethod, Inc.

Protocolのおさらい

• Javaでいうところのインターフェイスのようなもの

6Ⓒ Classmethod, Inc.

protocol Comparable { func compareTo(other: Self) -> Bool}

#cmdevio

Protocolのおさらい

• Protocolに定義できる宣言は

• メソッド

• プロパティ

• subscript

7Ⓒ Classmethod, Inc.

func append(x: Generator.Element)

var hashValue: Int { get }

subscript(index: Int) -> Generator.Element

#cmdevio

Protocolのおさらい

• Protocolに定義できる宣言は

• イニシャライザ

• typealias

• 演算子

8Ⓒ Classmethod, Inc.

init(floatLiteral value: Double)

typealias Element

func == (lhs: Self, rhs: Self) -> Bool

#cmdevio

Protocolのおさらい

• Selfは定義したProtocolに準拠した型を示す

9Ⓒ Classmethod, Inc.

protocol Equatable { func == (lhs: Self, rhs: Self) -> Bool}struct Entity { let id: Int}extension Entity: Equatable {}func == (lhs: Entity, rhs: Entity) -> Bool { return lhs.id == rhs.id}

#cmdevio

Protocolのおさらい

• Selfは定義したProtocolに準拠した型を示す

10Ⓒ Classmethod, Inc.

protocol Equatable { func == (lhs: Self, rhs: Self) -> Bool}struct Entity { let id: Int}extension Entity: Equatable {}func == (lhs: Entity, rhs: Entity) -> Bool { return lhs.id == rhs.id} EquatableのSelfはここではEntityとしてふるまう

#cmdevio

Protocolのおさらい

• Selfはドット経由でProtocolの中で用いれるtypealiasにアクセスできる

11Ⓒ Classmethod, Inc.

protocol Containable { typealias InnerType func contain(content: Self.InnerType)}

#cmdevio

Protocol Extensionとは• Protocolのおさらい

• Extensionのおさらい

• Protocol Extensionとは

12Ⓒ Classmethod, Inc.

Extensionのおさらい

• Objective-Cでいうところのカテゴリのようなもの

13Ⓒ Classmethod, Inc.

extension Int { func power(times: Int) -> Int { return Int( pow(Double(self), Double(times)) ) }}

#cmdevio

Extensionのおさらい

• Objective-Cでいうところのカテゴリのようなもの

14Ⓒ Classmethod, Inc.

extension Int { func power(times: Int) -> Int { return Int( pow(Double(self), Double(times)) ) }} Int型に累乗計算をするpowerメソッドを追加

#cmdevio

Extensionのおさらい

• Extensionに定義できる宣言は

• 計算プロパティ(クラス、ストラクチャに対して) • タイププロパティ • メソッド • subscript • イニシャライザ • ネストされた型

15Ⓒ Classmethod, Inc. #cmdevio

Extensionのおさらい

• Extensionで既存の型をProtocolに 準拠できる

16Ⓒ Classmethod, Inc.

protocol Writable { func write(content: Self)}extension String: Writable { func write(content: String) { .... }}

#cmdevio

Extensionのおさらい

• class, struct, enumに対して宣言できた

17Ⓒ Classmethod, Inc.

extension SomeClass {}extension SomeStruct {}extension SomeEnum {}

#cmdevio

Protocol Extensionとは• Protocolのおさらい

• Extensionのおさらい

• Protocol Extensionとは

18Ⓒ Classmethod, Inc.

Protocol Extension とは

• class, struct, enum に加えて protocol に対してもExtensionが 宣言できるようになった

19Ⓒ Classmethod, Inc.

protocol Writable { func write(content: Self)}extension Writable { …}

#cmdevio

Topics for today

• Protocol Extensionとは

• Protocol Extension詳細

• 標準APIの変更

20Ⓒ Classmethod, Inc.

Protocol Extension 詳細

21Ⓒ Classmethod, Inc.

• Protocolに対する実装

• Extension対象への制約

• Selfへの制約

Protocol に対する実装• Protocol 本体での宣言に対する デフォルト実装をExtensionで決められる

22Ⓒ Classmethod, Inc.

protocol NumberComponent { typealias NumberType var defaultNumber : NumberType { get }}extension NumberComponent { typealias NumberType = Int var defaultNumber: Int { return 1 }} #cmdevio

Protocol に対する実装• Protocol 本体での宣言に対する デフォルト実装をExtensionで決められる

23Ⓒ Classmethod, Inc.

protocol NumberComponent { typealias NumberType var defaultNumber : NumberType { get }}extension NumberComponent { typealias NumberType = Int var defaultNumber: Int { return 1 }}

デフォルトの NumberTypeはInt

デフォルトのdefaultNumberはIn

#cmdevio

Protocol に対する実装

• デフォルト実装は準拠する型で実装する必要がない

24Ⓒ Classmethod, Inc.

class NumberRepository: NumberComponent {

}

#cmdevio

Protocol に対する実装

• デフォルト実装は準拠する型で実装する必要がない

25Ⓒ Classmethod, Inc.

class NumberRepository: NumberComponent {

}デフォルト実装が宣言されているときはエラーにならない

#cmdevio

Protocol に対する実装• Protocol本体のインターフェイスを使って 実装できる

26Ⓒ Classmethod, Inc.

protocol SequenceType { func map<T>( transform: Self.Generator.Element -> T ) -> [T] func filter( includeElement: Self.Generator.Element -> Bool ) -> [Self.Generator.Element]}

#cmdevio

Protocol に対する実装• Protocol本体のインターフェイスを使って 実装できる

27Ⓒ Classmethod, Inc.

protocol SequenceType { func map<T>( transform: Self.Generator.Element -> T ) -> [T] func filter( includeElement: Self.Generator.Element -> Bool ) -> [Self.Generator.Element]}

個々の要素をマッピングするメソッド

要素をフィルタリングするメソッド

#cmdevio

Protocol に対する実装• Protocol本体のインターフェイスを使って 実装できる

28Ⓒ Classmethod, Inc.

extension SequenceType { func filterMap<T>( includeElement: Self.Generator.Element -> Bool, transform: Self.Generator.Element -> T ) -> [T] { return filter(includeElement) .map(transform) }} #cmdevio

Protocol に対する実装• Protocol本体のインターフェイスを使って 実装できる

29Ⓒ Classmethod, Inc.

extension SequenceType { func filterMap<T>( includeElement: Self.Generator.Element -> Bool, transform: Self.Generator.Element -> T ) -> [T] { return filter(includeElement) .map(transform) }}

要素をフィルタリングしたあとで マッピングするメソッド

#cmdevio

Protocol Extension 詳細

30Ⓒ Classmethod, Inc.

• Protocolに対する実装

• Extension対象への制約

• Selfへの制約

Extension対象への制約

• Extension対象への制約を ジェネリクスと同じwhere構文でつけられる

31Ⓒ Classmethod, Inc.

extension SequenceType where Generator.Element == Bool { var anyTrue: Bool { return reduce(false) { acc, elem in acc || elem } } }

#cmdevio

Extension対象への制約

• Extension対象への制約を ジェネリクスと同じwhere構文でつけられる

32Ⓒ Classmethod, Inc.

extension SequenceType where Generator.Element == Bool { var anyTrue: Bool { return reduce(false) { acc, elem in acc || elem } } }

Protocolへの実装を 利用する際に 満たす必要のある制約

#cmdevio

Extension対象への制約

• Extension対象への制約を ジェネリクスと同じwhere構文でつけられる

33Ⓒ Classmethod, Inc.

// true[true, false, false].anyTrue// false[false, false, false].anyTrue

#cmdevio

34Ⓒ Classmethod, Inc.

SequenceType Generator.Element

Array<Bool> Element = Bool

Extension対象への制約Bool

var anyTrue

#cmdevio

35Ⓒ Classmethod, Inc.

SequenceType Generator.Element

Array<Bool> Element = Bool

Extension対象への制約Bool

var anyTrue

anyTrueプロパティの 宣言を行った際に

#cmdevio

36Ⓒ Classmethod, Inc.

SequenceType Generator.Element

Array<Bool> Element = Bool

Extension対象への制約Bool

var anyTrue

呼び出した型が SequenceTypeに 準拠しているかチェック

#cmdevio

37Ⓒ Classmethod, Inc.

SequenceType Generator.Element

Array<Bool> Element = Bool

Extension対象への制約Bool

var anyTrue

SequenceTypeの Generator.Elementが Boolか チェック

#cmdevio

38Ⓒ Classmethod, Inc.

SequenceType Generator.Element

Array<Bool> Element = Bool

Extension対象への制約Bool

var anyTrue

SequenceTypeのGenerator.Elementが Boolなのでデフォルト実装を使える

#cmdevio

Extension対象への制約

• Extension対象への制約を ジェネリクスと同じwhere構文でつけられる

39Ⓒ Classmethod, Inc.

// true[true, false, false].anyTrue// false[false, false, false].anyTrue

Generator.Element == Bool を満たす型に対しては anyTrueプロパティを呼び出せる

#cmdevio

Extension対象への制約

• Extension対象への制約を 満たさないような型に対しては準拠していても インターフェイスを呼び出せない

40Ⓒ Classmethod, Inc.

// エラー[1, 2, 3].anyTrue[3.4, 5.6, 3.2].anyTrue

#cmdevio

41Ⓒ Classmethod, Inc.

SequenceType Generator.Element

Array<Int> Element = Int

Extension対象への制約Bool

var anyTrue

SequenceTypeの Generator.Elementが Boolかチェック

#cmdevio

42Ⓒ Classmethod, Inc.

SequenceType Generator.Element

Array<Int> Element = Int

Extension対象への制約Bool

var anyTrue

SequenceTypeのGenerator.Elementが Boolではないので デフォルト実装を使えない

#cmdevio

Extension対象への制約

• Extension対象への制約を 満たさないような型に対しては準拠していても インターフェイスを呼び出せない

43Ⓒ Classmethod, Inc.

// エラー[1, 2, 3].anyTrue[3.4, 5.6, 3.2].anyTrue

Generator.Element == Boolの制約に合わないため、 anyTrueプロパティは呼び出せない

#cmdevio

Protocol Extension 詳細

44Ⓒ Classmethod, Inc.

• Protocolに対する実装

• Extension対象への制約

• Selfへの制約

Selfへの制約

• Protocolに準拠した型を示すSelfもExtensionの 制約対象とできる

45Ⓒ Classmethod, Inc.

protocol Ordered { func precedes(other: Self) -> Bool}

#cmdevio

Selfへの制約

• Protocolに準拠した型を示すSelfもExtensionの 制約対象とできる

46Ⓒ Classmethod, Inc.

protocol Ordered { func precedes(other: Self) -> Bool}「先行する」という関係をprecedesメソッドで 定義したOrderedプロトコル

#cmdevio

Selfへの制約

• Protocolに準拠した型を示すSelfもExtensionの 制約対象とできる

47Ⓒ Classmethod, Inc.

extension Ordered where Self: Comparable { func precedes(other: Self) -> Bool { return self < other }}

#cmdevio

Selfへの制約

• Protocolに準拠した型を示すSelfもExtensionの 制約対象とできる

48Ⓒ Classmethod, Inc.

extension Ordered where Self: Comparable { func precedes(other: Self) -> Bool { return self < other }}

Comparableプロトコルに準拠した型に 対しては既存の演算子を先行する関係の定義に流用する

#cmdevio

• Protocolに準拠した型を示すSelfもExtensionの 制約対象とできる

Selfへの制約

49Ⓒ Classmethod, Inc.

extension Int: Ordered {}1.precedes(0)extension Double: Ordered {}(1.2).precedes(4.1)

#cmdevio

Selfへの制約

50Ⓒ Classmethod, Inc.

OrderedComparable

Double Int

func precedes

#cmdevio

Selfへの制約

51Ⓒ Classmethod, Inc.

OrderedComparable

Double Int

Orderedに既存の型を準拠させる際に

func precedes

#cmdevio

Selfへの制約

52Ⓒ Classmethod, Inc.

OrderedComparable

Double Int

既存の型がComparableに準拠しているか チェックされる

func precedes

#cmdevio

Selfへの制約

53Ⓒ Classmethod, Inc.

OrderedComparable

Double Int

Comparableにも準拠していれば デフォルト実装を使える

func precedes

#cmdevio

• Protocolに準拠した型を示すSelfもExtensionの 制約対象とできる

Selfへの制約

54Ⓒ Classmethod, Inc.

extension Int: Ordered {}1.precedes(0)extension Double: Ordered {}(1.2).precedes(4.1)Comparableプロトコルに準拠した型に対しては 先行する関係を示したprecedeメソッドを 実装なしで呼べる

#cmdevio

• Protocolに準拠した型を示すSelfもExtensionの 制約対象とできる

Selfへの制約

55Ⓒ Classmethod, Inc.

struct Rational: Ordered { var numer: Int var denom: Int} // エラー

#cmdevio

Selfへの制約

56Ⓒ Classmethod, Inc.

OrderedComparable

Rational

既存の型がComparableに準拠しているか チェックされる

func precedes

#cmdevio

Selfへの制約

57Ⓒ Classmethod, Inc.

OrderedComparable

Rational

func precedes

Comparableに準拠していなければ デフォルト実装が使えない

#cmdevio

• Protocolに準拠した型を示すSelfもExtensionの 制約対象とできる

Selfへの制約

58Ⓒ Classmethod, Inc.

struct Rational: Ordered { var numer: Int var denom: Int} // エラー

Comparableプロトコルに準拠しない型に対しては precedesメソッドの実装が必要

#cmdevio

Topics for today

• Protocol Extensionとは

• Protocol Extension詳細

• 標準APIの変更

59Ⓒ Classmethod, Inc.

標準APIの変更• グローバル関数の変更

60Ⓒ Classmethod, Inc.

グローバル関数の変更

• Swift 1.2 ではProtocol Extensionがつかえず、 Protocolに対するメソッド呼び出しは グローバル関数で実現されていた。

理想

現実

61Ⓒ Classmethod, Inc.

contains([1, 2, 3, 4], 5)

[1, 2, 3, 4].contains(5)

#cmdevio

グローバル関数の変更

• Swift 1.2 ではProtocol Extensionがつかえず、 Protocolに対するメソッド呼び出しは グローバル関数で実現されていた。

理想

現実

62Ⓒ Classmethod, Inc.

contains([1, 2, 3, 4], 5)

[1, 2, 3, 4].contains(5)

要素がEquatableなSequenceTypeに対して . でメソッド呼び出しを行いたかった

第一引数をProtocolに準拠した型の値とした 関数で呼び出していた

#cmdevio

グローバル関数の変更理想

現実

63Ⓒ Classmethod, Inc.

contains(filter([1, 2, 3, 4]) { a in a % 2 == 0 }, 5)

[1, 2, 3, 4].filter { a in a % 2 == 0}.contains(5)

要素がEquatableなSequenceTypeに対して . でメソッド呼び出しを行いたかった

第一引数をProtocolに準拠した型の値とした 関数で呼び出していた

#cmdevio

64

グローバル関数の変更

• Swift 1.2 -> 2 でグローバル関数の多くがProtocolのメソッドに移行した

65Ⓒ Classmethod, Inc.

https://developer.apple.com/library/prerelease/ios/releasenotes/General/iOS90APIDiffs/modules/Swift.html

#cmdevio

グローバル関数の変更

• Swift 1.2 -> 2 でグローバル関数の多くがProtocolのメソッドに移行した

66Ⓒ Classmethod, Inc.

https://developer.apple.com/library/prerelease/ios/releasenotes/General/iOS90APIDiffs/modules/Swift.html

#cmdevio

グローバル関数の変更

• Swift 1.2 -> 2 でグローバル関数の多くがProtocolのメソッドに移行した

Swift 1.2

Swift 2

67Ⓒ Classmethod, Inc.

contains([1, 2, 3, 4], 5)

[1, 2, 3, 4].contains(5)

#cmdevio

• Swift 1.2 -> 2 でグローバル関数の多くがProtocolのメソッドに移行した Swift 1.2

Swift 2

グローバル関数の変更

68Ⓒ Classmethod, Inc.

contains(filter([1, 2, 3, 4]) { a in a % 2 == 0 }, 5)

[1, 2, 3, 4].filter { a in a % 2 == 0}.contains(5)

#cmdevio

69

•プロトコル拡張を使ってプログラミングするhttp://ez-net.jp/article/4F/W2t_ixtF/OKrMCHTLSvx7/

• Protocol-Oriented Programming in Swifthttps://developer.apple.com/videos/wwdc/2015/?id=408

70Ⓒ Classmethod, Inc.

References

#cmdevio

71Ⓒ Classmethod, Inc.

One more thing…

72Ⓒ Classmethod, Inc.

73Ⓒ Classmethod, Inc.

http://dev.classmethod.jp/smartphone/wwdc-2015-

swift-2/