Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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() {}
}

I get an error "Type 'Object' does not conform to protocol 'Parent'. The reason I get this error is because I defined children to be an array of Foo rather than AnyObject. Is there any way I can make this work?

like image 472
MAH Avatar asked Aug 01 '15 20:08

MAH


2 Answers

Requiring AnyObject in the protocol means the children array must be able to accept AnyObject entries. But it sounds like you want Bar's children to be only Foo objects.

Instead, you can give the protocol an associated type:

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

class Foo { }

class Bar: Parent {
    var children = [Foo]()
    init() {}
}
like image 56
jtbandes Avatar answered Sep 25 '22 02:09

jtbandes


If you always want an array of type AnyObject you have to specify it in your class:

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

but if you can use a more specific protocol with a typealias you can rewrite you protocol like so:

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 way your former conformance of your class works but you have to consider that this protocol can only be used as generic constraint and therefore only in functions and generic 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>()
like image 32
Qbyte Avatar answered Sep 23 '22 02:09

Qbyte