我的 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?
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?