-
-
Save quesera2/a57242183bee8d4e645c75caf9fb0006 to your computer and use it in GitHub Desktop.
Example of type erasure with Pokemon
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Thunder { } | |
class Fire { } | |
protocol Pokemon { | |
associatedtype PokemonType | |
func attack(move:PokemonType) | |
} | |
struct Pikachu: Pokemon { | |
typealias PokemonType = Thunder | |
func attack(move: Thunder) { print("⚡️") } | |
} | |
class Charmander: Pokemon { | |
func attack(move: Fire) { print("🔥") } | |
} | |
class Raichu: Pokemon { | |
typealias PokemonType = Thunder | |
func attack(move: Thunder) { print("⚡️") } | |
} | |
// 付随型をジェネリクスに置き換えた抽象クラスを作る | |
// Swiftの言語仕様上、抽象クラスはないので、実際には「抽象クラスのようなもの」です | |
private class _AnyPokemonBase<PokemonType>: Pokemon { | |
func attack(move:PokemonType) { | |
// 空実装を提供する。オリジナルは abstruct() という関数を呼んでいる | |
fatalError() | |
} | |
} | |
// 抽象クラスを継承したラッパーを作る | |
private class _AnyPokemonBox<ConcretePokemon: Pokemon> : _AnyPokemonBase<ConcretePokemon.PokemonType> { | |
let base :ConcretePokemon | |
init(_ base :ConcretePokemon) { | |
self.base = base | |
} | |
override func attack(move: ConcretePokemon.PokemonType) { | |
self.base.attack(move) | |
} | |
} | |
// AnyPokemonでは、_AnyPokemonBoxに処理を移譲する | |
final class AnyPokemon <PokemonType>: Pokemon { | |
private let _box : _AnyPokemonBase<PokemonType> | |
required init<U:Pokemon where U.PokemonType == PokemonType>(_ pokemon: U) { | |
self._box = _AnyPokemonBox(pokemon) | |
} | |
func attack(move: PokemonType) { | |
self._box.attack(move) | |
} | |
} | |
let thunderAttack = Thunder() | |
let electricPokemon = [AnyPokemon(Pikachu()), AnyPokemon(Raichu())] | |
for pokemon in electricPokemon { | |
pokemon.attack(thunderAttack) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
without protocol oriented.
// 英語は適当
I think...
Than deceive compiler by trick, provided
abstract
class can easy understood.Each framework are making abstract class of their own.
Are you serious??