2014-12-05 43 views
5

如果Swift通用類型約束是協議名稱,那麼我可以要求兩種類型(約束於該協議)的類型相同。例如:如何在Swift通用中說「同一類」

protocol Flier {} 
struct Bird : Flier {} 
struct Insect: Flier {} 
func flockTwoTogether<T:Flier>(f1:T, f2:T) {} 

功能flockTwoTogether可以與鳥和鳥或與昆蟲和昆蟲被調用,但不與鳥和昆蟲。這是我想要的限制。到現在爲止還挺好。

但是,如果我嘗試用一​​個類名相同的事情,這是行不通的:

class Dog {} 
class NoisyDog : Dog {} 
class WellBehavedDog: Dog {} 
func walkTwoTogether<T:Dog>(d1:T, d2:T) {} 

的問題是,我可以叫walkTwoTogether與WellBehavedDog和NoisyDog。這是我想要防止的。

實際上有兩個問題在這裏:

  • 有沒有辦法說walkTwoTogether不能以WellBehavedDog和NoisyDog叫?

  • 這是一個錯誤?我問,因爲如果我不能使用泛型來說這個,很難看出爲什麼泛型約束成爲類名稱是有用的,因爲我們可以用普通函數得到相同的結果。

+0

這對我來說好像是預期的行爲?你已經將可選項限制爲Dog類型。您的兩個子類都符合該類型,並且聲明中的任何內容都不會限制它們。如果有辦法做你想做的事情,我會期望它需要一個'where'子句,如'',但是也會拋出一個錯誤。 – cmyr 2014-12-05 19:40:06

+0

@cmyr是的,當然我嘗試過。這就是爲什麼我問我在做什麼不是如何去做,是否有可能做到這一點。 :) – matt 2014-12-05 19:43:28

+0

這一切都有效,如果'狗'是一個協議。通用約束不能在非協議類型上強制執行。 *(東西類型擦除)* – mattt 2014-12-05 19:44:31

回答

3

不是答案本身,但一些數據或許...問題是,當你撥打:

walkTwoTogether(NoisyDog(), WellBehavedDog()) 

斯威夫特可以只是把這兩種情況下,就好像他們是實例Dog(aka,upcast) - 我們需要這個,所以我們可以調用方法A的子類A。 (我知道你知道這一點。)

斯威夫特不上溯造型到協議,所以要做到這一點的唯一方法是指定的子類的協議,超符合:

protocol Walkable {} 
extension NoisyDog : Walkable {} 
extension WellBehavedDog: Walkable {} 
func walkTwoTogether<T: Dog where T: Walkable>(d1:T, d2:T) { } 

walkTwoTogether(NoisyDog(), WellBehavedDog()) 
// error: type 'Dog' does not conform to protocol 'Walkable' 

錯誤消息明確顯示是怎麼回事 - 調用此版本的walkToTogether的唯一途徑是子類的實例上溯造型到Dog,但Dog不符合Walkable

+0

幸運的是,我沒有提出這個問題,因爲我最初提出了這個問題,這是爲了區分Dog和NoisyDog! – matt 2014-12-05 21:20:54

+0

不允許有子類! – 2014-12-05 21:32:18

1

我要說的是,這應該被認爲是一個錯誤,因爲inout參數類型更改的要求,因爲他們應該是:

func walkTwoTogether<T:Dog>(inout d1:T, d2:T) { 

現在有預期的行爲,你只能通過兩個相同類型的值。 (在Swift 1.2和Swift 2 beta 5中測試)

+0

是的,沒有。這是合法的:'var d:Dog = WellBehavedDog(); walkTwoTogether(&d,NoisyDog())'無論如何,如果有錯誤,我認爲我們可以說的最多的是它的不一致性;目前還不清楚哪個是正確的。 – matt 2015-08-20 22:28:28

+0

@matt你說得對,它可以是任何一個。在你的情況下,你必須用'inout'標記兩個參數。有趣的是,如果你不使用通用約束,它的行爲幾乎相同。 – Qbyte 2015-08-20 22:41:02

+1

我比以前更加困惑!但是你的數據很有趣,毫無疑問。 – matt 2015-08-21 00:41:52

相關問題