Last active
September 28, 2017 23:19
-
-
Save tarunon/4d0f33a6d2525ee94b6a3ce95c7b637b to your computer and use it in GitHub Desktop.
This file contains 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
// 多変数の型パラ持ちのprotocolでtype-erasureを書く時に、共変性をサポートしたいが | |
// 素直なtype-erasureでは引数にバラバラにpropertyを渡すことでしか共変な型消しをinitできなかった。 | |
class Animal {} | |
class Cat: Animal {} | |
protocol A { | |
associatedtype X | |
var x: X { get } | |
var int: Int { get } | |
var string: String { get } | |
} | |
struct CatA: A { | |
typealias X = Cat | |
var x: Cat | |
var int: Int | |
var string: String | |
} | |
struct AnyA<X>: A { | |
var x: X | |
var int: Int | |
var string: String | |
} | |
extension AnyA { | |
init<O: A>(_ a: O) where O.X == X { | |
self.init(x: a.x, int: a.int, string: a.string) | |
} | |
} | |
var catA = CatA(x: Cat(), int: 1, string: "1") | |
//var animalA: AnyA<Animal> = AnyA(catA) // できない | |
var animalA: AnyA<Animal> = AnyA(x: catA.x, int: catA.int, string: catA.string) // 出来るけど面倒 | |
// Tupleでフィールドをまとめてそれを受け取るinitを追加 | |
extension A { | |
var erasureConfig: (x: X, int: Int, string: String) { | |
return (x: x, int: int, string: string) | |
} | |
} | |
extension AnyA { | |
init(config: (x: X, int: Int, string: String)) { | |
self.init(x: config.x, int: config.int, string: config.string) | |
} | |
} | |
// var animalB: AnyA<Animal> = AnyA(config: catA.erasureConfig) // これもダメ | |
// Tupleを返すFunctionにする | |
extension A { | |
var erasureBuilder: () -> (x: X, int: Int, string: String) { | |
return { _ in self.erasureConfig } | |
} | |
} | |
extension AnyA { | |
init(builder: () -> (x: X, int: Int, string: String)) { | |
self.init(config: builder()) | |
} | |
} | |
var animalB: AnyA<Animal> = AnyA(builder: catA.erasureBuilder) // やったぜ | |
// ↑ @autoclosureで横着するとコンパイラクラッシュ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment