假设我有以下协议:
protocol Identifiable {
var id: Int {get}
var name: String {get}
}
而且我有以下结构:
struct A: Identifiable {
var id: Int
var name: String
}
struct B: Identifiable {
var id: Int
var name: String
}
如您所见,我必须“遵循”结构A和结构B中的Identifiable协议。但是想象一下,如果我还有N个需要符合该协议的结构……我不想“复制/粘贴”
‘一致性(变量ID:整数,变量名称:字符串)
所以我创建了一个 协议扩展 :
extension Identifiable {
var id: Int {
return 0
}
var name: String {
return "default"
}
}
现在,通过此扩展,我可以创建符合Identifiable协议的结构,而不必同时实现这两个属性:
struct C: Identifiable {
}
现在的问题是我不能为id属性或name属性设置值:
var c: C = C()
c.id = 12 // Cannot assign to property: 'id' is a get-only property
发生这种情况是因为在可识别协议中,ID和名称仅是可获取的。现在,如果将id和name属性更改为 {get set}, 则会出现以下错误:
类型“ C”不符合协议“可识别”
发生此错误是因为我尚未在协议扩展中实现setter …所以我更改了协议扩展:
extension Identifiable {
var id: Int {
get {
return 0
}
set {
}
}
var name: String {
get {
return "default"
}
set {
}
}
}
现在错误消失了,但是如果我将新值设置为id或name,它将获得默认值(getter)。当然, 二传手是空的 。
我的问题是: 我必须在设置器中放入哪段代码? 因为如果我添加 self.id = newValue, 它会崩溃(递归)。
提前致谢。
似乎您想stored property
通过协议扩展将a添加到类型中。但是,这是不可能的,因为扩展不能添加存储的属性。
我可以向您展示一些替代方案。
最简单的方法(可能您已经想像到了)是使用类而不是结构。
class IdentifiableBase {
var id = 0
var name = "default"
}
class A: IdentifiableBase { }
let a = A()
a.name = "test"
print(a.name) // test
缺点:在这种情况下,您的A类需要继承,
IdentifiableBase
并且由于在Swift中没有多重继承,因此这将是A唯一可以继承的类。
该技术在游戏开发中非常流行
struct IdentifiableComponent {
var id = 0
var name = "default"
}
protocol HasIdentifiableComponent {
var identifiableComponent: IdentifiableComponent { get set }
}
protocol Identifiable: HasIdentifiableComponent { }
extension Identifiable {
var id: Int {
get { return identifiableComponent.id }
set { identifiableComponent.id = newValue }
}
var name: String {
get { return identifiableComponent.name }
set { identifiableComponent.name = newValue }
}
}
现在您可以使您的类型符合Identifiable
简单的书写方式
struct A: Identifiable {
var identifiableComponent = IdentifiableComponent()
}
测试
var a = A()
a.identifiableComponent.name = "test"
print(a.identifiableComponent.name) // test
问题内容: 我正在尝试使用Swift协议扩展,却发现这种行为令人困惑。您能帮我得到我想要的结果吗? 请参阅代码最后4行的注释。(如果需要,可以将其复制粘贴到Xcode7游乐场)。谢谢!! 问题答案: 简短的答案是协议扩展不执行类多态性。这是有一定道理的,因为协议可以被结构或枚举采用,并且因为我们不希望仅在没有必要的地方采用协议来引入动态调度。 因此,在中,实例变量(可能更准确地写为)并不意味着您认
扩展说明 RPC 协议扩展,封装远程调用细节。 契约: 当用户调用 refer() 所返回的 Invoker 对象的 invoke() 方法时,协议需相应执行同 URL 远端 export() 传入的 Invoker 对象的 invoke() 方法。 其中,refer() 返回的 Invoker 由协议实现,协议通常需要在此 Invoker 中发送远程请求,export() 传入的 Invoker
协议和扩展 你可以扩展一个已经存在的类型来采纳和遵循一个新协议, 就算是你无法访问现有类型的源代码也行. 扩展可以添加新的属性、方法和下标到已经存在的类型, 并且因此允许你添加协议需要的任何需要. protocol TextRepresentable { var textualDescription: String { get } } // 此处并无Dice这个类, 以及其sides属性
问题内容: 我正在尝试使用协议扩展在某些方法上添加默认行为,例如: 您可能会猜到,键盘永远不会消失。我真的看不出问题出在哪里。这是语言限制吗?有人已经成功做到了吗? 编辑: 正如@Logan所建议的,默认协议的方法实现不适用于标记为的协议。但是,具有以下签名 我已经测试了默认的实现,它似乎运行良好: 问题答案: 我不能100%积极,但是我相信这是正在发生的事情: 无法从访问协议扩展。由于是协议,因
本文作为HPB知识库的一种扩展阅读, RLP编码是数据序列化的主要方法,本文介绍RLP编码的主要规则和原理分析,RLP编码具有较好的数据处理效率,尤其是将长度和类型统一作为前缀,实际上RLP是基于ASCII编码的一种结构化扩充,既能表示长度还能表示类型,是一种非常紧凑的结构化编码方案 RLP(Recursive Length Prefix,递归长度前缀)是一种编码算法,用于编码任意的嵌套结构的二进
问题内容: 如何设置协议的可选属性?例如,UITextInputTraits具有许多可选的读/写属性。当我尝试以下操作时,出现编译错误(无法在“ textInputTraits”中分配给“ keyboardType”): 通常,在访问协议的可选属性时,您会添加问号,但这在分配值时不起作用(错误:无法分配给该表达式的结果): 该协议如下所示: 问题答案: 在Swift中是不可能的(还好吗?)。从AD