この記事はSwift Advent Calendar 2016の24日目の記事です。
Swift4で導入されるConditional conformances(条件付き適合)について調べてみました。
Conditional conformances(条件付き適合)とは
Swift Evolutionでは、今後のSwift向けのいろいろな機能が検討されています。
Xcode8がでるまでは、Swift3向けの機能でもりあがっていましたが、Swift3もおちついてきて、Swift4向けの機能の検討にうつってきています。
先日、SE-0143 Conditional conformances がSwift4にむけて承認されました。
Conditional conformancesとはなんでしょうか。
Genericsはプロトコルに適合できませんが、これを特定の条件下でできるようにしたのが、Conditional conformancesです。
例えば、下記のようなArrayを作ります。
ArrayのElementがEquatableの場合、Array
下記のようにArrayのArrayの==演算をしようとしても、通常はエラーとなります。
let a2: Array<Int> = [1,2,3,4,5]
let diffBetweenArray = (a1 == a2)
let diffBetweenArryOfArray = ([a1] == [a2]) // Error!
Array自体にEquatableを適合させようとしても、Swift3.0ではエラーとなってしまいます。
extension Array:Equatable where Element: Equatable {
static func == (lhs: Array<Element>,rhs: Array<Element>) -> Bool {
return .....
}
}
Conditional conformances(条件付き適合)が採用されると、例えば、Arrayは、ElementがEquqtableに適合していた場合、Equatableに適合することができるようになります。
Arrayで==が使えるけど?
Array
public func ==<Element : Equatable>(lhs: ContiguousArray<Element>, rhs: ContiguousArray<Element>) -> Bool
ジェネリクスの動的な型チェック
ジェネリクスがプロトコルに適合することで、動的な型チェックも可能となります。
下記はSE-0143にあげてあった例ですが、プロトコルPに適合しているかどうかでArrayの型チェックを行うことができます。
これは意外に実プロジェクトで役にたちそうな気がしますね。
func doSomething()
}
struct S: P {
func doSomething() { print("S") }
}
// Array conforms to P if it's element type conforms to P
extension Array: P where Element: P {
func doSomething() {
for value in self {
value.doSomething()
}
}
}
// Dynamically query and use conformance to P.
func doSomethingIfP(_ value: Any) {
if let p = value as? P {
p.doSomething()
} else {
print("Not a P")
}
}
doSomethingIfP([S(), S(), S()]) // prints "S" three times
doSomethingIfP([1, 2, 3]) // prints "Not a P"
これからのジェネリクス
Conditional conformancesや今後のジェネリクスについては、Swiftのジェネリクスの設計方針(Generics manifesto)にも書いてあります。
このConditional conformancesについては、Swift4で導入される予定です。