具有从AnyObject继承的关联类型的通用协议看不到另一个协议继承自AnyObject

时间:2017-04-25 14:00:44

标签: swift

假设我有一个名为Car的泛型类绑定协议,它具有从AnyObject继承的关联类型。该协议定义了一个变量和一个addPassenger()函数,并为其提供了一个默认实现。

我需要从AnyObject继承关联类型,因为我希望能够使用===过滤掉调用addPassenger()时已经知道的实例。

protocol Car: class {
    associatedtype T: AnyObject
    var passengers: [T] { get set }
    func addPassenger(_ passenger: T)
}

extension Car {
    func addPassenger(_ passenger: T) {
        guard passengers.index(where: { $0 === passenger }) == nil else {
            return
        }
        passengers.append(passenger)
    }
}

然后我有另一个名为Passenger的协议,它必须可以与Car一起使用:

protocol Passenger: AnyObject {}

最后,假设我有一个名为SomeClass的类的实例,它符合Car协议并定义了一个乘客数组:

class SomeClass: Car {
    internal var passengers: [Passenger] = []
}

然而,这是不可能的,因为显然Passenger不符合AnyObject:

 error: type 'SomeClass' does not conform to protocol 'Car'
 note: unable to infer associated type 'T' for protocol 'Car'
 note: inferred type 'Passenger' (by matching requirement 'passengers') is invalid: does not conform to 'AnyObject'

知道我错过了什么吗?

1 个答案:

答案 0 :(得分:1)

实施协议时,必须使用具体类型作为associatedType。我认为这与在编译时需要知道用于泛型类型的类型这一事实有关。因此,您的案例编译原因与此相同:

protocol A { }

class B: A { }

func f<T: A>(x: T) { }

// doesn't compile
let x: A = B()
f(x: x)

// compiles
let x = B()
f(x: x)

因为通用类型T需要在编译时知道。

在您的情况下,如果您希望SomeClass使用符合Passenger的不同类型,则可以使用泛型来使其正常工作:

class SomeClass<T: Passenger>: Car {
    var passengers: [T] = []
}

或者,您当然可以使用基类

class BasePassenger: AnyObject {}

class SomeClass: Car {
    var passengers: [BasePassenger] = []
}

希望这有帮助!祝你好运!