Swift 类型擦除尝试:“引用无效的关联类型”

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

请帮助我了解缺少的内容。(或者,是否有可能首先创建一个非通用类型擦除包装器?)

Cri*_*tik 5

您的代码无法编译,因为关联的类型需要在编译时通过提供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)