Swift:类型不符合协议

时间:2016-04-23 14:45:18

标签: swift swift2 protocols

protocol A {}
protocol B {
    var a: A { get }
}

struct StructA: A {}
struct StructB {
    var a: StructA
}
extension StructB: B {}

这会产生错误:

  

键入' StructB'不符合协议' B'

StructA已符合协议AStructB的属性a返回StructA类型。这似乎是一个协议B符合类型。

但为什么?

Swift版本为2.2的Xcode版本7.3

2 个答案:

答案 0 :(得分:3)

为了更好地说明当前代码的问题,假设您有一个StructC : A

您的协议B表示您可以将StructC分配给a(因为它符合A) - 但StructB表示您无法分配StructC 1}}到StructA类型。因此StructB不符合B

解决方案是将a的类型从StructA更改为A as Rahul says,或者更好的是,您可以使用泛型。

使用泛型的好处是,一旦您使用给定的StructB创建a - 该属性的类型将由Swift推断,为您提供更好的类型安全性。例如,为其分配StructA后,其类型将为StructA。如果您为其分配StructC,则其类型将为StructC

为此,我们只需向协议associatedtype添加B即可。这将定义一个“占位符”类型,然后我们可以在符合B的类型中实现该类型。然后,我们可以在T中定义通用类型StructB,它将提供AType的“实施” - 确保它符合A。因此,我们现在可以自由地将StructAStructC分配给a,而不会失去类型安全性。

protocol A {}
protocol B {

    // new associated type to hold the type of "a" which conforms to A
    associatedtype AType:A
    var a: AType { get }
}

struct StructA: A {}
struct StructC:A {}

// define the new generic T which conforms to A
struct StructB<T:A> {

    // define the type of a as the generic T, which conforms to A (and thus conforms with the protocol)
    var a : T
}

extension StructB: B {}

let s = StructB(a: StructA())
s.a // "a" is now of type StructA

let s1 = StructB(a: StructC())
s1.a // "a" is now of type StructC

答案 1 :(得分:2)

因为Swift是静态类型的,并且不依赖于动态调度。你可以做类似下面的事情。

import UIKit

protocol A {}
protocol B {
    var a: A { get }
}

struct StructA: A {}
struct StructB {
    var a: A = StructA()
}
extension StructB: B {}