2015-08-24 35 views
2

在斯威夫特2子協議父協議相關聯的類型,我有一個協議:指定與斯威夫特

protocol Protocol { 
    typealias Type 
} 

當我想用Protocol沒有定義使用什麼類型Type

var protocol1: Protocol 

然後我發現了以下錯誤:

Protocol 'Protocol' can only be used as a generic constraint because it has Self or associated type requirements

這是CLEA r爲什麼這不起作用。


我有另一種協議,其從第一協議繼承和指定該相關類型Type應該是一個String。發生

protocol AnotherProtocol: Protocol { 
    typealias Type = String 
} 

同樣的錯誤,當我嘗試使用此協議:

var protocol2: AnotherProtocol 

Protocol 'AnotherProtocol' can only be used as a generic constraint because it has Self or associated type requirements

爲什麼我收到了這樣的錯誤,雖然我已經指定了相關的類型?

第二個協議是否有另一種方式來指定父協議的關聯類型,而不必在每個實現第二個協議的類中再次指定它?

回答

2

您的錯誤不是來自您的協議的聲明或定義,它來自於您如何使用它們。有兩種使用協議的基本方法:作爲僞類型或作爲約束。當你聲明這樣的變量:

var protocol1: Protocol 

您正在使用的協議就像是一個類型:protocol1類型爲Protocol。這與將其用作約束不同。如果它作爲一個約束其他類型符合協議:

struct SomeStruct: Protocol {... 

現在,您可以使用協議中任何一種方式,但也有一些缺點兩種方式。首先,你不能存儲一個「協議作爲約束」的異構集合,而當你使用協議作爲一個類型時你可以。其次,如果對自我或關聯類型有要求,則不能再使用該協議作爲類型。

所以,這是我認爲你正在尋找的東西。你的第一個協議:

protocol Protocol { 
    typealias Type 
} 

然後第二:

protocol InheritingProtocol { 
    typealias Type = String 
} 

現在,如果你想要的東西,以符合第二協議,它必須作爲一個約束。這意味着某些類型的符合該協議,然後您可以獲得該類型的一些實例

struct SomeType : InheritingProtocol {} 

let someInstance = SomeType() 
+0

謝謝你的回答。我需要傳遞第二個協議,而不必知道實現該協議的類/結構。但正如你所說,如果協議具有關聯類型,那麼使用協議作爲類型是不可能的。第二個協議有一個關聯的類型,但很明顯,這是什麼類型。我覺得這很奇怪。使用這個協議作爲一個類型應該是可能的,因爲所有關聯的類型都被聲明瞭。 – Marian

+0

您可以使用類型擦除封裝器 – oisdk

+0

不幸的是,實現第二個協議的類需要有一個超類。所以它必須實現協議,並且不能繼承其他類,但是使用類型擦除的包裝器必須使用創建的類。 – Marian