Skip to content

Instantly share code, notes, and snippets.

@ktanaka117
Created March 6, 2016 13:22
Show Gist options
  • Save ktanaka117/88837d20e6c4e4462701 to your computer and use it in GitHub Desktop.
Save ktanaka117/88837d20e6c4e4462701 to your computer and use it in GitHub Desktop.
try! Swift 2016のGwendolyn WestonさんによるType Erasureセッションの復習
import Foundation
// 💡: 元の例では型が指定されてなかったけど、この場合多分enumかな
enum Element {
case Electric, Fire
}
/********** Abstract Pokemon **********/
protocol Pokemon {
typealias PokemonType
func attack(move: PokemonType)
}
class AnyPokemon <PokemonType>: Pokemon {
// 💡: PokemonTypeからVoidが返る関数の型
let method: PokemonType -> Void
// ❓: 元が(_ pokemon: U)引数名を記述しない例だった。引数名あったほうがわかりやすい期がするけれど、これは宗教の問題?
required init<U: Pokemon where U.PokemonType == PokemonType> (pokemon: U) {
method = pokemon.attack
}
// 💡💡💡: ここで型が消えてることが確認出来る。これによって実装のattack()の引数がなんであれ実行できる。これがType Erasureの美味しいところ???
func attack(move: PokemonType) {
method(move)
}
}
/********** Concrete Pokemon **********/
class Pikachu: Pokemon {
func attack(move: Element) { print("⚡️") }
}
class Charmander: Pokemon {
func attack(move: Element) { print("🔥") }
}
// 💡: これによってPokemonプロトコルを採用したConcrete Pokemonを、AnyPokemonを通すことでオブジェクト化できる
//AnyPokemon(pokemon: <#T##U#>)
let pikachu = AnyPokemon(pokemon: Pikachu())
let charmander = AnyPokemon(pokemon: Charmander())
// 💡: attack()の引数はPokemonType。型が消えているのでなんでもよくて、Concrete Pokemonのタイプで実装しているElement型を引数にしなくてよい。
//pikachu.attack(<#T##move: PokemonType##PokemonType#>)
pikachu.attack(.Electric)
charmander.attack(.Fire)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment