2014-09-25 79 views
1

我最近下載了xCode 6並一直在玩Swift語言。到目前爲止,我很享受它。我正在閱讀Swift特性,其中一個我很喜歡的是推理。然而,在我創建的用於在Swift中實踐創建協議的代碼示例中,我遇到了一個我不太明白的問題,因此希望有人能幫助澄清發生了什麼。也許我錯過了一些東西。因此,爲了該代碼示例Swift,推理和協議行爲

我創建了一個協議動物

protocol Animal 
{ 
    func speak() 
} 

然後創建一個符合動物協議,例如狗和貓類

class Dog: Animal { 

    func speak() 
    { 
     println("Woof"); 
    } 
} 

然後創建了狗和貓的變量,以檢查它的工作如預期

var animal1 = Dog() 
    var animal2 = Cat() 

    println(animal1.speak()) 
    println(animal2.speak()) 

沒有問題爲止。於是我決定將這些通過對象添加到一個數組和循環,並打印出來

var ar = [animal1, animal2]; 

     for var i = 0; i < ar.count; i++ 
     { 
      var an = ar[i] 

      println(an.speak()) 
     } 

但是我得到一個錯誤說「AnyObject不符合協議的‘動物’,以及一個警告說」變量被推斷爲具有可能意外的「AnyObject」類型。我認爲,由於推論,它應該自動實現狗和貓符合動物協議。當我以前打印說法時,我不需要指定動物類型。所以後來我更新了循環方法中的變量,因此明確規定,對象符合動物類型,像這樣

var an : Animal = ar[i] 

這消除了警告,但錯誤依然存在。爲什麼會這樣?我明確告訴它,這個對象符合Animal協議。我能做到這一點在Objective-C沒有這樣

for(int i = 0; i < array.count; i++) 
    { 
     id <Animal> an = [ar objectAtIndex:i]; 
     [an speak]; 
    } 

一個問題,那麼,爲什麼不這項工作斯威夫特?

我再更新animal1和animal2的正本報關,所以它看起來像這樣

var animal1 : Animal = Dog() 
var animal2 = Cat() 

或者,我可以做到這一點

var animal1 = Dog() 
    var animal2 : Animal = Cat() 

和錯誤消失了。爲什麼我只需要更新其中一個變量來表示符合協議Animal,而不是兩者?

如果有人能夠澄清這裏發生了什麼,請將此表示感謝!也許我只是失去了一些東西提前

回答

1

在SWIFT有單繼承(一個類只能從一個類繼承),但多個協議通過。

類型推斷無法弄清楚Cat和Dog之間有什麼共同之處,因爲它們不會從同一個類繼承。如果你把Animal變成一個類,你的循環就可以正常工作。

一個類可以實現多個協議,而2個類可以有多個共同的協議。由於類型推斷在確定分配給陣列的類型時不能選擇其中之一,因此它會選擇使其成爲Array<AnyObject>

要解決此問題,只需要把數組類型明確:

var ar: [Animal] = [animal1, animal2] 

animal1animal2,不管他們的實際類型的,是實現Animal協議類的兩個實例。

在此代碼:

var animal1 : Animal = Dog() 
var animal2 = Cat() 

您提供的編譯器足夠的信息讓類型推斷確定數組類型:animal1具有Animal類型,animal2Cat一個實例,這又實現了協議

+0

Objective-c也有多個協議通過,但是沒有這個問題。作爲測試,我很快在Objc-C中創建了隨機協議,並將其添加到貓類,但不是狗類。然而,在Obj-c中,我可以檢查一個類是否符合協議,在Swift中可以做類似的事情嗎? – AdamM 2014-09-25 10:16:25

+0

你可以用'is'來檢查。例如,「如果狗是動物」。更好的是,如果投射成功,你可以做一個返回包含某個值的可選值的投射,如果投射不成功,則可以爲零。例如,'var dog = arr [0] as? Dog' – Kirsteins 2014-09-25 10:22:07

+1

在obj-c中它可以工作,因爲它不使用泛型,所以編譯器不會嘗試對數組中的元素執行類型檢查。相反,它們必須是相同的類型,或者從共同的祖先繼承/實現。 – Antonio 2014-09-25 10:26:03

1

感謝我猜原因數組不是推斷爲Animal是因爲類可以符合多種協議,但只能從一個類繼承。如果您的CatDog也符合像Pet這樣的協議,您將如何知道是否推斷爲AnimalPet陣列。

在你的情況只是聲明明確的類型數組:

var ar: [Animal] = [animal1, animal2] 

for var i = 0; i < ar.count; i++ 
{ 
    var an = ar[i] 
    println(an.speak()) 
} 
0

我們應該推斷爲動物數組,如何說上面,請看看這個也

在你的情況只是聲明顯式類型arr ay:

var array: [Animal] = [animal1, animal2] 

for animal in array 
{ 
    if let an = animal is Dog { 
    print(" Hey! Dog speaking:\(an.speak())") 
    } if let an = animal is Cat { 
    print(" Hey! Cat speaking:\(an.speak())") 
    } 

}