簡體   English   中英

具有從AnyObject繼承的關聯類型的通用協議不會將其他協議視為從AnyObject繼承

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

假設我有一個稱為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協議並定義了一系列Passengers:

class SomeClass: Car {
    internal var passengers: [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'

知道我想念什么嗎?

在實現協議時,必須將具體類型用作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] = []
}

希望這可以幫助! 祝好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM