我最近下载了xCode 6并且一直在使用Swift语言。到目前为止,我很享受。我正在阅读Swift功能,其中一个我非常喜欢推断。然而,在我创建的代码示例中,我在Swift中练习创建协议,我遇到了一个我不太了解的问题所以希望有人帮助澄清正在发生的事情。也许我错过了一些东西。所以对代码示例
我创建了一个协议Animal
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())
}
但是我收到一条错误说&#34; AnyObject不符合协议&#34; Animal&#34;以及一个警告说&#34;变量推断有类型&#34; AnyObject&#34;这可能是出乎意料的。我认为由于推断,它应该自动实现Dog和Cat符合Animal协议。当我以前打印讲话方法时,我不需要指定动物类型。那么我在循环方法中更新了变量,因此它明确地声明该对象符合Animal类型,如此
var an : Animal = ar[i]
这会删除警告,但错误仍然存在。为什么会这样?我已明确告诉它该对象符合Animal协议。我可以在Objective-c中做到这一点,没有像这样的问题
for(int i = 0; i < array.count; i++)
{
id <Animal> an = [ar objectAtIndex:i];
[an speak];
}
那为什么这个在Swift中不起作用?
然后我更新了animal1和animal2的原始声明,所以它看起来像这样
var animal1 : Animal = Dog()
var animal2 = Cat()
或者我可以这样做
var animal1 = Dog()
var animal2 : Animal = Cat()
错误消失了。为什么我只需要更新其中一个变量以符合协议Animal的状态,而不是两者都是?
如果有人澄清这里发生了什么,将不胜感激?也许我只是缺少一些东西
提前致谢
答案 0 :(得分:1)
我认为原因数组不推断为Animal
,因为类可以符合多个协议但只能从一个类继承。如果您的Cat
和Dog
也符合Pet
之类的协议,您如何知道是推断Animal
还是Pet
数组。
在你的情况下,只声明显式类型数组:
var ar: [Animal] = [animal1, animal2]
for var i = 0; i < ar.count; i++
{
var an = ar[i]
println(an.speak())
}
答案 1 :(得分:1)
在swift中有单继承(一个类只能从一个类继承),但是多个协议采用。
类型推断无法弄清楚Cat和Dog之间的共同点,因为它们不会从同一个类继承。如果你将Animal变成一个类,你的循环就可以了。
一个类可以实现多个协议,两个类可以有多个共同的协议。由于类型推断在确定要分配给数组的类型时无法选择其中一种,因此它选择将其设为Array<AnyObject>
。
要解决此问题,只需将数组类型设为显式:
var ar: [Animal] = [animal1, animal2]
animal1
和animal2
,无论其实际类型如何,都是实现Animal
协议的类的实例。
在此代码中:
var animal1 : Animal = Dog()
var animal2 = Cat()
您正在为编译器提供足够的信息以让类型推断确定数组类型:animal1
具有Animal
类型,animal2
是Cat
的实例,它依次为实现该协议
答案 2 :(得分:0)
我们应该推断数组为Animal,上面怎么说,请看看这个
在你的情况下,只声明显式类型数组:
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())")
}
}