【问题标题】:Generic protocol with an associated type inheriting from AnyObject does not see another protocol as inheriting from AnyObject具有从 AnyObject 继承的关联类型的通用协议不会将另一个协议视为从 AnyObject 继承
【发布时间】:2017-04-25 14:00:43
【问题描述】:

假设我有一个名为 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)
    }
}

然后我有另一个协议,称为乘客,它必须与 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'

知道我错过了什么吗?

【问题讨论】:

标签: swift


【解决方案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] = []
}

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

【讨论】:

  • "实现协议时必须使用具体类型作为关联类型。" - 这很有趣,这是在文档中吗?我不记得见过它。
猜你喜欢
  • 1970-01-01
  • 2021-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多