Skip to content

Instantly share code, notes, and snippets.

@takasek
Last active April 2, 2016 05:10
Show Gist options
  • Save takasek/70437dde0556880703dd3e634595ddb2 to your computer and use it in GitHub Desktop.
Save takasek/70437dde0556880703dd3e634595ddb2 to your computer and use it in GitHub Desktop.
しょっぱなに質問したら、要求を実現するための型消去の実装の検討に付き合っていただいた…! #CodePiece #cswift
// 最初のコード
protocol FoodType {}
struct Spirit: FoodType {}
struct Meet: FoodType {}
protocol MonsterType {
typealias Food: FoodType
}
protocol DevilType: MonsterType {}
protocol ZombieType: MonsterType {}
struct Devil: DevilType {
typealias Food = Spirit
}
struct Zombie: ZombieType {
typealias Food = Meet
}
func getMonster<T: FoodType>(food: T) -> MonsterType<T> {
switch food {
case is Spirit:
return Devil()
default:
return Zombie()
}
}
// Tは引数についての制約だからこれが通らないのはわかるんだけど、戻り値に対する制約ってどうやって書けばいい…?
// 熊谷さん「TはFoodではなくMonsterTypeにするのがいいですね」
func getMonster<T: MonsterType>(food: T.Food) -> T {
switch food {
case is Spirit:
return Devil()
default:
return Zombie()
}
}
// →「型消去」
// 型消去用struct Monster を作る!
protocol MonsterType {
typealias Food: FoodType
func eat(food: Food) // ←NEW!
}
struct Monster: MonsterType { // まだうまく動かない
private let monster: Any
typealias Food = FoodType
init<M: MonsterType>(_ monster: M) {
self.monster = monster
}
func eat(food: Food) { (monster as! MonsterType).eat(food) }
}
struct Devil: DevilType {
typealias Food = Spirit
func eat(food: Food) {
}
}
struct Zombie: ZombieType {
typealias Food = Meet
func eat(food: Food) {
}
}
func summonMonster(food: FoodType) -> Monster {
switch food {
case is Spirit:
return Monster(Devil())
default:
return Monster(Zombie())
}
// あきおさん「Foodが決まってもMonsterは一意に決まらないよね」
// 熊谷さん「でんきポケモンが欲しいって言ったらピカチュウしか来なくてライチュウは来ない! みたいなことですね」
// まあそれはともかくとして、foodによって決め打ちでDevilかZombieかを返したい、として… まだ通ってない
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment