假设我有一个名为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'
知道我错过了什么吗?
答案 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] = []
}
希望这有帮助!祝你好运!