Swift协议扩展:无法分配给属性:”是仅获取属性

时间:2019-01-10 18:41:19

标签: swift

我想我不明白协议扩展应该如何工作。

我尝试过:

protocol P {
    var h: [String: Any] { set get }
}

extension P {
    var h: [String: Any] {
        get {
            return [:]
        }
        set {}
    }
}

struct S: P {   
    init() {
        self.h = ["o": "o"]
    }
}

我的目标是S具有P的属性,不需要在结构定义中重新声明它。

但是,当我创建let s = S()时,s.h总是等于[:]而不是["o":"o"]

当然,这是因为我的二传手是空的,但是我不知道该怎么做。

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

  

我的目标是S具有P的属性,不需要在结构定义中重新声明它。

您尝试执行此操作的方式是不可能的。协议要求某些行为。符合类型必须提供那些行为。如果您需要存储来实现该行为,则一致性类型必须提供存储。

如果您不希望存储就可以了,那么扩展名可以像您一样返回值。但是您不能返回计算值,也无法存储。您尝试做的事是不可能的。您正在考虑的是类,而不是协议。 (如果您要使用类,那很好。使用类。它们没有错。)

思考为什么在Swift中无法做到这一点的一种好方法是考虑以下情况。假设您的P协议以某种形式存在,可以实现所需的功能。现在,在一个模块中,我们定义:

struct S {}

此结构不需要存储。该模块中对S()的任何调用均不分配任何内容。 (或者,为S提供一些属性,它将分配一些特定的内存量。)

现在在其他模块中,扩展S以符合P

extension S: P {}

h的存储将去哪里?甚至在加载此扩展时,实例可能已经存在。如果有多个协议需要附加存储并将所有协议都附加到S,该怎么办?这些属性应该是S结构的偏移量吗?该顺序对于编译后的代码非常重要。这不是不可能解决的(ObjC使用一种称为关联对象的技术来解决),但这是对语言的一大补充,并且阻止了许多重要的优化,而Swift并没有这样做。

答案 1 :(得分:0)

您亲近了,只需要在S结构中重新声明h变量

protocol P {
    var h: [String: Any] { set get }
}

extension P {
    var h: [String: Any] {
        get {
            return [:]
        }
        set {}
    }
}

struct S: P {
    var h: [String: Any]

    init() {
        self.h = ["o": "o"]
    }
}

let s = S()
print(s.h) // ["o": "o"]