我的 class 可以覆盖协议 属性 输入 Swift 吗?

Can my class override protocol property type in Swift?

protocol Parent {
     var children: [AnyObject] { get set }
}

class Foo {
}

class Bar: Parent { //error happens here
    var children = [Foo]()

    init() {}
}

我得到一个错误“Type 'Object' does not conform to protocol 'Parent'。我得到这个错误的原因是因为我将 children 定义为 Foo 而不是 AnyObject 的数组。是否有我有什么办法可以让这个工作?

如果协议声明存在类型为 [AnyObject] 的 getter 和 setter,则意味着必须存在 getter 和 setter,不是 class.

的子类型

你的代码在逻辑上是错误的——因为你可以设置,例如一些 [Int](协议说这是可能的)到 [Foo] 类型的变量(class 只有这个 var )

所以这实际上是唯一正确的方法。

protocol Parent {
    var children: [AnyObject] { get set }
}

class Foo {
}

class Bar: Parent { //error happens here
    var children = [AnyObject]()

    init() {}
}

在 swift 2.0 中,typealias 可能是另一种选择。

不,您不能更改 属性 的类型。

将此添加到您的栏中 class:

var childrenObject: Foo {
    get {
        return self.children as! Foo
    }
}

在协议中要求 AnyObject 意味着 children 数组 必须 能够接受 AnyObject 条目。但听起来你希望 Bar 的 children 只是 Foo objects.

相反,您可以给协议一个 associated type:

protocol Parent {
    associatedtype Child
    var children: [Child] { get set }
}

class Foo { }

class Bar: Parent {
    var children = [Foo]()
    init() {}
}

如果您总是想要 AnyObject 类型的数组,则必须在 class:

中指定它
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 }
}

通过这种方式,您以前对 class 的遵从性有效,但您必须考虑到该协议只能用作通用约束,因此只能在函数和通用声明中使用:

// --- 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>()

协议答案的替代方案可能会给您一些协议所没有的好处。

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)

相关:How in Swift specify type constraint to be enum?