LoginSignup
0
1

More than 1 year has passed since last update.

anyについて

Posted at

protocolを利用する上で

protocol 内にassociatedTypeやSelfがあった場合、
例:

protocol Caffeteria {
associatedType Caffe
var name: String { get }
func place(_ cafe: Caffe )
}

class StarBucks: Caffeteria {
typealias Caffe = String
var name = "StarBucks"
func place(_ cafe: String) {  "StarBucks is at Shinjuku" } 
}

let starBucks: Caffeteria = StarBucks()
// コンパイルエラーが出る。

なぜなら、starBucksを生成する際に、プロトコルであるCaffeteriaを型として利用しているが、型の中のassociatedTypeが何に準拠しているかその時点でわからない。(Selfの場合も同様)。

TypeErasure

なので、別のクラスを生成してあげて、associatedTypeが何の準拠しているのかを伝えてあげる。

class AnyCaffeteria: Caffeteria {
let name: String
let _place : (Caffe) -> Void?

init <X: Caffeteria >(_ base: X)  where X.Caffe = Caffe {
 name = base.name
 _place = base.place
}
 func place(_ cafe: String) {
  _place(cafe)
}
}
let starBucks: AnyCaffeteria = AnyCaffeteria(StarBucks())

AnyCaffeteriaを生成する際に、StarBucksのクラスをbase入れてあげる。そこで初めてassociatedTypeの型がわかるようにinit時にwhereを用いている。イメージ:whereは超静的に型をみてくれている。

Anyを用いる

上記の件に対して、anyを使うことで簡単に記述が可能になる。

protocol Caffeteria {
  associatedtype Caffe
  var name: String { get }
  func place(_ cafe: Caffe)
}

class StarBucks: Caffeteria {
  typealias Caffe = String
  var name = "Starbucks"
  func place(_ cafe: String) { "Starbucks is at Shinjuku" }
}

let starbucks: any Caffeteria = StarBucks()

any Caffeteriaのように記述することで、静的に出なく動的に判断してくれる!なので、コンパイルが通る!
正確には動的Dispatchを行なってくれている。

注意点

Existential Containerを用いて、メモリを多く取ってしまうため、パフォーマンスがあまり良くない。

イメージ:
何人誕生日パーティーに集まるかわからないので、とりあえずとても大きいケーキを用意しておく!

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1