问题

我正在做一个制造的练习来尝试实现一个打字擦除的容器.

 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()
}
 

我故意不希望我的AnyAnimal容器是AnyAnimal<T>容器.因为,我希望能够在Array<AnyAnimal>中存储许多Animal实例.

但是,正如您在上面的代码中所看到的,编译器正在抱怨AnyAnimal类.我的理解是,Mover的协议要求将通过where初始化器中的通用AnyAnimal子句解决.

请帮我理解缺少什么. (或者,是否甚至可以首先创建一个非通用的字体删除包装器?)

  最佳答案

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

  相同标签的其他问题

swiftgenericsswift-protocolstype-erasure