はじめに
僕のSwiftで最も好きな文法はExtensionです笑
基礎的なExtensionの使い方はこちらをみてみてください。
TargetedExtensionというものがあるらしいので、みていきましょう。
Extensionとは?
詳細なエクステンションの説明は省きますが、エクステンションは以下のように構造体やクラス、プロトコルを拡張してメソッドなどを追加できます。
例を見てみましょう。
extension Int {
var minus10: Self {
return self - 10
}
func plus100() -> Self {
return self + 100
}
}
print(200.minus10) //190
print(200.plus100().plus100().minus10) //390
こちらも合わせてご覧ください(メソッドチェーン)
TargetedExtensionとは?
前項の例だといいのですが、命名によってはこのメソッドは既にあるものなのか、自分で作ったものなのかわからない場合がありますし、Xcodeの予測変換でメソッドやプロパティが自分で作った数だけ多くなるので、見辛くなってしまうかもしれません。できればXcodeの補完を汚さずに、自作のメソッドなどにアクセスしたいです。
このような時に役に立つのがTargetedExtensionです。
前項のプログラムを修正していきましょう。
protocol SomeComapatible {
associatedtype ComapatibleType
var own: ComapatibleType { get }
}
class Some<T> {
private let base: T
init(_ base: T) {
self.base = base
}
}
extension SomeComapatible {
var own: Some<Self> {
return Some(self)
}
}
extension Int: SomeComapatible { }
extension Some where T == Int {
var minus10: Int {
return base - 10
}
func plus100() -> Int {
return base + 100
}
}
こうすることで、以下のようにown
を間に挟まないとminus10
プロパティやplus100
メソッドにアクセスできないようにできました。
print(1000.minus10) //エラー
print(1000.own.plus100()) //1100
解説
ステップ1
このプロトコルを採用したものはown
プロパティを持つようにする。
protocol SomeComapatible {
associatedtype ComapatibleType
var own: ComapatibleType { get }
}
ステップ2
Int
に先ほどのプロパティを準拠させます。しかし、own
プロパティの実装がありませんので、次で実装しましょう。
extension Int: SomeComapatible { }
ステップ3
以下のように実装します。Some<Self>
のSelf
はプロトコルSomeComapatible
を準拠させた具体的な型なので、今回はInt
ですね。
そして、return Some(self)
のself
はprint(1000.own.plus100())
このように書いた時の1000
のことです。
このように、ジェネリクスも用いてあげることで、Int
だけでなくString
などでも同じown
を利用する事ができます。
class Some<T> {
private let base: T
init(_ base: T) {
self.base = base
}
}
extension SomeComapatible {
var own: Some<Self> {
return Some(self)
}
}
ステップ4
では、具体的にメソッドなどを定義していきます。
extension Some where T == Int {
var minus10: Int {
return base - 10
}
func plus100() -> Int {
return base + 100
}
}
このminus10
とplus100
はT
がInt
の時のみ使えると言う条件を付け足しました。
base
はInt
なので、実際は1000
などが入ってきます。
おわりに
メソッドチェーンはこのような考慮がかけています。ぜひ、この記事を参考に書き換えてみてください。