Can't create an Array of types conforming to a Protocol in Swift Can't create an Array of types conforming to a Protocol in Swift swift swift

Can't create an Array of types conforming to a Protocol in Swift


Let's say, if we could put an instance of Thing into array foos, what will happen?

protocol Foo {    typealias BazType    func bar(x:BazType) -> BazType}class Thing: Foo {    func bar(x: Int) -> Int {        return x.successor()    }}class AnotherThing: Foo {    func bar(x: String) -> String {        return x    }}var foos: [Foo] = [Thing()]

Because AnotherThing conforms to Foo too, so we can put it into foos also.

foos.append(AnotherThing())

Now we grab a foo from foos randomly.

let foo = foos[Int(arc4random_uniform(UInt32(foos.count - 1)))]

and I'm going to call method bar, can you tell me that I should send a string or an integer to bar?

foo.bar("foo") or foo.bar(1)

Swift can't.

So it can only be used as a generic constraint.

What scenario requires a protocol like this?

Example:

class MyClass<T: Foo> {        let fooThing: T?        init(fooThing: T? = nil) {                self.fooThing = fooThing        }        func myMethod() {                let thing = fooThing as? Thing // ok                thing?.bar(1) // fine                let anotherThing = fooThing as? AnotherThing // no problem                anotherThing?.bar("foo") // you can do it                // but you can't downcast it to types which doesn't conform to Foo                let string = fooThing as? String // this is an error        }}


I have been playing with your code trying to understand how to implement the protocol. I found that you can't use Typealias as a generic type because it is just an alias not a type by itself. So if you declare the Typealias outside your protocol and your class you can effectively use it in your code without any problem.

Note: the Typealias has the Int type in its declaration, that way you can always use the alias instead of the Int type and use all of its associated methods and functions.

Here's how I make it work:

typealias BazType = Intprotocol Foo{  func bar(x:BazType) -> BazType}class Thing: Foo {  func bar(x: BazType) -> BazType {    return x.successor()  }}let elements: Array<Foo> = [Thing(), Thing()]