protocol Parent {
var children: [AnyObject] { get set }
}
class Foo {
}
class Bar: Parent { //error happens here
var children = [Foo]()
init() {}
}
我收到错误“类型'对象'不符合协议'父'。我得到这个错误的原因是因为我将子节点定义为Foo而不是AnyObject的数组。我有什么方法可以做到这一点工作?
答案 0 :(得分:9)
在协议中要求AnyObject意味着children
数组必须能够接受AnyObject
个条目。但听起来你希望Bar
的孩子只是Foo
个对象。
相反,您可以为协议指定associated type:
protocol Parent {
associatedtype Child
var children: [Child] { get set }
}
class Foo { }
class Bar: Parent {
var children = [Foo]()
init() {}
}
答案 1 :(得分:2)
如果你总是想要一个AnyObject类型的数组,你必须在你的类中指定它:
class Bar: Parent {
var children = [AnyObject]()
init() {}
}
但如果您可以使用更具体的typealias
协议,您可以像这样重写协议:
protocol Parent {
// in Swift 1 and 2: use `typealias` instead of `associatedtype`
associatedtype T: AnyObject // this makes sure that all instances in the array are definitely of type `AnyObject` / classes
var children: [T] { get set }
}
这样你以前对你的类的一致性有效,但是你必须考虑这个协议只能用作泛型约束,因此只能用在函数和泛型声明中:
// --- this does work
func someFunc<T: Parent, U: Parent>(p1: T, p2: U) { /* ... */ }
class SomeClass<T: Parent> { /* ... */ }
// --- this doesn't work
let parent: Parent
let array: [Parent]
// here you can only use types which conform to the protocol
// but not the protocol itself as generic arguments
let something = SomeClass<Parent>()
答案 2 :(得分:1)
如果协议声明存在[AnyObject]类型的getter和setter,则意味着必须有这样的getter和setter,而不是该类的子类型。
你的代码在逻辑上是错误的 - 因为你可以设置,例如某些[Int](协议说它可能)到[Foo]类型的变量(类只有这个变量)< / p>
所以这实际上是唯一正确的方法。
protocol Parent {
var children: [AnyObject] { get set }
}
class Foo {
}
class Bar: Parent { //error happens here
var children = [AnyObject]()
init() {}
}
在swift 2.0中,typealias可能是另一种选择。
答案 3 :(得分:0)
不,你不能改变一个属性的类型。
将此添加到您的栏类:
var childrenObject: Foo {
get {
return self.children as! Foo
}
}
答案 4 :(得分:0)
协议答案的替代方案可能会给您一些协议所带来的好处。
class Parent<T : RawRepresentable> where T.RawValue == Int {
var value : T
init(withValue v : T) {
self.value = v
}
}
enum testOne : Int {
case one
case two
}
enum testTwo : Int {
case three
case four
}
class ChildOne : Parent<testOne> {}
class ChildTwo : Parent<testTwo> {}
let c1 = ChildOne(withValue: testOne.one)
print(c1.value)
let c2 = ChildTwo(withValue: testTwo.three)
print(c2.value)