Mat*_* H. 3 generics type-erasure swift swift-protocols
我正在做一个虚构的练习来尝试实现一个类型擦除的容器。
import Foundation
protocol MoverType {
func move()
}
extension MoverType {
func move() { print("\(type(of: self)) is moving") }
}
class Slithering: MoverType {}
class Walking: MoverType {}
class Trotting: MoverType {}
protocol Animal {
associatedtype Mover: MoverType
var mover: Mover { get }
}
class Snake: Animal {
let mover = Slithering()
}
class Dog: Animal {
let mover = Trotting()
}
class Human: Animal {
let mover = Walking()
}
class AnyAnimal: Animal { // ERROR: Type 'AnyAnimal' does not conform to protocol 'Animal'
var _mover: () -> Mover
init<A: Animal>(animal: A) where Mover == A.Mover {
_mover = {
return animal.mover
}
}
// ERROR HERE: "Reference to invalid associated type "Mover" of of type "AnyAnimal"
var mover: Mover { fatalError() }
}
let d = AnyAnimal(animal: Dog())
let s = AnyAnimal(animal: Snake())
let animals = [d, s] // Array<AnyAnimal>
for a in animals {
a.mover.move()
}
Run Code Online (Sandbox Code Playgroud)
我故意不希望我的AnyAnimal容器成为AnyAnimal<T>容器。因为,我希望能够将许多Animal实例存储在Array<AnyAnimal>.
然而,正如您在上面的代码中看到的,编译器正在抱怨该类AnyAnimal。据我了解,协议要求将通过初始化程序中的Mover通用子句来解决。whereAnyAnimal
请帮助我了解缺少的内容。(或者,是否有可能首先创建一个非通用类型擦除包装器?)
您的代码无法编译,因为关联的类型需要在编译时通过提供Mover协议的具体实现来解析。
您可以做的就是删除MoverType协议:
struct AnyMover: MoverType {
private let mover: MoverType
init(_ mover: MoverType) {
self.mover = mover
}
func move() {
mover.move()
}
}
class AnyAnimal: Animal {
let mover: AnyMover
init<A: Animal>(animal: A) {
mover = AnyMover(animal.mover)
}
}
Run Code Online (Sandbox Code Playgroud)