Can my class override the protocol property type in Swift?

protocol Parent { var children: [AnyObject] { get set } } class Foo { } class Bar: Parent { //error happens here var children = [Foo]() init() {} } 

I get an error "Type" Object "does not match the Parent protocol. The reason I get this error is because I defined the children as an array of Foo, not AnyObject. Is there a way to make this work?

+8
swift protocols
source share
5 answers

Requiring AnyObject in the protocol means that the children array must be able to accept AnyObject entries. But it looks like you want the Bar kids to be just Foo objects.

Instead, you can specify a protocol related type :

 protocol Parent { associatedtype Child var children: [Child] { get set } } class Foo { } class Bar: Parent { var children = [Foo]() init() {} } 
+6
source share

If you always need an array of type AnyObject, you must specify it in your class:

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

but if you can use a more specific protocol with typealias , you can rewrite the protocol like this:

 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 } } 

Thus, your previous correspondence of your class works, but you should consider that this protocol can be used only as a general restriction and, therefore, only in functions and general declarations:

 // --- 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
source share

If the protocol declares that there is a getter and setter of type [AnyObject], than this means that there should be such a getter and setter, and not a subtype of this class.

Your code will be logically incorrect - because you could set, for example, some [Int] (the protocol says it is possible) a variable of the type [Foo] (the class only has this var)

So this is actually the only right way.

 protocol Parent { var children: [AnyObject] { get set } } class Foo { } class Bar: Parent { //error happens here var children = [AnyObject]() init() {} } 

In swift 2.0 typealias may be another option.

+1
source share

No, you cannot change the type of property.

Add this to your class bar:

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

An alternative to a protocol response that may give you some advantages that are not in the protocol.

 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) 

Related: How in Swift to specify a type restriction for an enumeration?

0
source share

All Articles