Swift Type Eraser is 何?

ググると出てくるやつ

多分 try! Swift 2016で発表があってそれのまとめ記事がよく出てくる。

protocol Pokemon {
    associatedtype Element
    var element: Element { get }
}

associatedtype を持つProtocolで変数を宣言するとエラーになる。

let pokemon: Pokemon
//  Protocol 'Pokemon' can only be used as a generic constraint because it has Self or associated type requirements
struct Thunder {}
struct Fire {}

class Pikachu: Pokemon {
    var element: Thunder { Thunder() }
}

class Raichu: Pokemon {
    var element: Thunder { Thunder() }
}

class Charmander {
    var element: Fire { Fire() }
}

具体型なら定義できる

    let pikachu: Pikachu
    let raichu: Raichu

でんきタイプポケモンの配列を定義するにはどうしたらいいか?

class AnyPokemon<PokemonType>: Pokemon {
    var element: PokemonType

    init<P: Pokemon>(_ pokemon: P) where P.Element == PokemonType {
        self.element = pokemon.element
    }
}
    let thumderPokemon1: AnyPokemon<Thunder> = AnyPokemon(Pikachu())
    let thumderPokemon2: AnyPokemon<Thunder> = AnyPokemon(Raichu())

当たり前という気がするのだが。。

Type Eraserの実装パターン

  • Closure APIKitのsendメソッドのクロージャーとかも、これに似てるかもしれない。

  • Box

ライブラリでよく使ってるので参考に

RealmSwift

ReSwfit

ReSwift

protocol AnyPokemon {
    var _element: Any { get }
}

protocol Pokemon: AnyPokemon {
    associatedtype Element
    var element: Element { get }
}

extension Pokemon {
    var _element: Any {
        element
    }
}

PokemonをAnyPokemonに準拠するという方法

let pokemons: [AnyPokemon] = [Pikachu(), Raichu()]

Carbon

Carbon

Boxパターンとかいうやつ