简体   繁体   English

具有从AnyObject继承的关联类型的通用协议不会将其他协议视为从AnyObject继承

[英]Generic protocol with an associated type inheriting from AnyObject does not see another protocol as inheriting from AnyObject

Suppose I have a generic class-bound protocol called Car that has an associated type which inherits from AnyObject. 假设我有一个称为Car的通用类绑定协议,该协议具有一个从AnyObject继承的关联类型。 This protocol has a variable and an addPassenger() function defined and provides a default implementation for it. 该协议具有一个变量和一个定义的addPassenger()函数,并为其提供默认实现。

I need the associated type to inherit from AnyObject because I want to be able to use === to filter out instances I already know about when calling 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)
    }
}

I then have another protocol called Passenger which must be usable with Car: 然后,我还有另一个名为“乘客”的协议,该协议必须可与Car一起使用:

protocol Passenger: AnyObject {}

Finally, suppose I have an instance of a class called SomeClass which conforms to the Car protocol and defines an array of Passengers: 最后,假设我有一个名为SomeClass的类的实例,该类符合Car协议并定义了一系列Passengers:

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

However, this is not possible because apparently Passenger does not conform to AnyObject: 但是,这是不可能的,因为乘客显然不符合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'

Any idea what am I missing? 知道我想念什么吗?

A concrete type must be used as the associatedType when implementing the protocol. 在实现协议时,必须将具体类型用作associatedType I think this has to do with the fact that the type used for generic type needs to be known at compile time. 我认为这与以下事实有关:用于通用类型的类型需要在编译时知道。 So, your case doesn't compile for the same reason as this: 因此,您的案例由于以下原因而无法编译:

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)

Because the generic type T needs to be known at compile time. 因为在编译时需要知道通用类型T。

In your case, if you want SomeClass to work with different types that conform to Passenger you can use generics to make it work: 在您的情况下,如果您希望SomeClass使用符合Passenger不同类型,则可以使用泛型使其工作:

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

or, you could of course use a base class instead 或者,您当然可以改用基类

class BasePassenger: AnyObject {}

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

Hope this helps! 希望这可以帮助! Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM