2017-04-25 58 views
0

假設我有一個名爲Car的通用類綁定協議,它具有從AnyObject繼承的關聯類型。該協議有一個變量和一個addPassenger()函數,併爲其提供了一個默認實現。具有從AnyObject繼承的關聯類型的泛型協議沒有看到從AnyObject繼承的另一個協議

我需要關聯的類型從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) 
    } 
} 

然後我有另一個稱爲乘客協議,該協議必須與汽車可用:

protocol Passenger: AnyObject {} 

最後,假設我有一個名爲SomeClass的類,它符合汽車協議,並限定一個陣列的一個實例旅客:

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' 

任何想法我錯過了什麼?

+1

我正在處理類似的問題,並提出這個問題:http://stackoverflow.com/questions/36867827/how-to-make-protocol-associated-type-require-protocol-inheritance-and-not-protoc。我認爲當前關聯類型必須是具體類型,而不是從基本協議要求繼承的協議類型。 –

+1

比較[在Swift中無法將協議用作其他協議中的關聯類型](http://stackoverflow.com/q/37360114/2976878)&[協議本身不符合?](http://stackoverflow.com/a/43408193/2976878) - Passenger確實不是符合AnyObject的類型。 – Hamish

回答

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] = [] 
} 

希望這有助於!祝你好運!

+0

「在實現協議時,必須使用具體類型作爲關聯類型。」 - 這很有趣,這是在文檔中?我不記得看到它。 – clawoo