Skip to content

Instantly share code, notes, and snippets.

@rintaro
Created October 6, 2017 08:48
Show Gist options
  • Save rintaro/c240100472967973de3f42e16080dfa1 to your computer and use it in GitHub Desktop.
Save rintaro/c240100472967973de3f42e16080dfa1 to your computer and use it in GitHub Desktop.
protocol CatProtocol {
associatedtype Food
func difficult<T>(to: T.Type, food: Food, me: Self) -> Self
}
class Cat : CatProtocol {
typealias Food = String
required init() {}
func difficult<T>(to: T.Type, food: String, me: Cat) -> Self {
fatalError()
}
}
class AnyCatBase<Food> {
func difficult<T>(to: T.Type, food: Food, me: AnyCatBase<Food>) -> Self { fatalError() }
}
final class AnyCatBox<Base: CatProtocol> : AnyCatBase<Base.Food> {
typealias Food = Base.Food
var _base: Base
init(_ base: Base) { _base = base }
override func difficult<T>(to: T.Type, food: Base.Food, me: AnyCatBase<Base.Food>) -> Self {
return type(of: self).init(_base.difficult(to: to, food: food, me: _base))
}
}
struct AnyCat<F> : CatProtocol {
typealias Food = F
var _box: AnyCatBase<Food>
init<Base: CatProtocol>(_ base: Base) where F == Base.Food {
_box = AnyCatBox(base)
}
private init(_ box: AnyCatBase<Food>) {
_box = box
}
func difficult<T>(to: T.Type, food: Food, me: AnyCat<Food>) -> AnyCat<Food> {
return AnyCat(_box.difficult(to: to, food: food, me: me._box))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment