我想我不明白协议扩展应该如何工作。
我尝试过:
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"]
。
当然,这是因为我的二传手是空的,但是我不知道该怎么做。
感谢您的帮助。
答案 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"]