简体   繁体   中英

Swift structs an protocols not work as expected

Following playground-ready code ;)

protocol Prot {
    static func instanceArray() -> [Self]
}

struct A {
    init() {
        // Do something
    }
}

extension A: Prot {
    static func instanceArray() -> [A] {
        return [A(), A()]
    }
}

func work() -> [Prot] {
    return A.instanceArray()
}

The compiler will throw an error at return A.instanceArray() : Cannot convert return expression of type [A] to return type [Prot]

Why is the compiler not able to convert these types even though A implements the protocol Prot ? I know that a workaround is to change the return type of instanceArray() to [Prot] but I don't really like this solution. Is this a compiler bug or a feature?

There is a away to get around it if you must

func work() -> [Prot] {
    return A.instanceArray().map{ $0 as Prot }
}

It will be easier to see what's going on if we eliminate all the extra stuff not needed in your example. So, consider this:

protocol Prot {}
struct A : Prot {}

let arr = [A(), A()] // 1: ok
let arr2 = [A(), A()] as [Prot] // 2: ok
let arr3 = arr as [Prot] // 3: compile error

The question is then, why is [2] legal but [3] is not? The difference is that we are allowed to form an array of A instances and type it as a [Prot] , but we are not allowed to cast an existing array variable, already typed as [A] , to a [Prot] .

You can call this a bug or a limitation of Swift if you want to, and you would certainly be justified in a filing a bug report, but in any case it's a well-known shortcoming having to do with the fact that protocols are just not quite full-fledged types.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM