swift - 在非类绑定协议的扩展中,实例必须被视为值类型
问题描述
这是代码:
protocol A {
var a: Int { get set }
}
extension A {
var convenientAccessor: Int {
get { return a }
set { a = newValue }
}
}
class B: A {
var a: Int = 0
}
func acceptsB (instance: B) {
instance.a = 1 // This compiles
instance.convenientAccessor = 2 // This does not
}
我有点理解这里的问题,但我真的很想得到更深入理解的人的回答,更重要的是我的问题的解决方法,即我想传递已知的类类型并能够使用方便的访问器不受我无法使用值类型的限制。就我而言,定义这些方便访问器的协议不应该是类绑定的(它们对值类型完全有效且有用),因此虽然这在技术上是一种解决方法,但我并不满意。
解决方案
让我们从总结开始:convenientAccessor
是一个可写属性,因此对其进行任何赋值都会导致突变。这种突变发生在你的函数内部。
问题是,当convenientAccessor
使用该属性时,编译器将instance
其视为协议A
,并且由于函数的参数是let
's,它不允许对它们进行突变,因为此时协议也可以由值类型实现。
我想到的两个解决方案是:
将协议限制
A
为仅类:protocol A: class
这会通知编译器只有类才能符合协议,这允许对任何类型的变量(
let
或var
)进行突变制作函数参数
inout
:func acceptsB (instance: inout B)
这会创建一个“写漏洞”,因为现在
instance
是可写的,因此对它的任何更改都会传播回上游,即使B
是值类型。
就个人而言,如果您计划仅使用类,我会选择#1,正如您在问题中提到的那样。
推荐阅读
- android - Android 上的 Ionic InAppBrowser 无法导航到自定义 URL 方案
- android - LabTest 通过但应用程序直到最后才去
- c++ - 使用 boost 线程时编译失败
- python - 为什么以这两种不同的方式在 Python 中使用 SVM 会给出非常不同的准确度分数?
- javascript - ReactJS / Javascript:单击提交按钮时呈现图形
- python - Opencv上的线性反转图像
- python - 在R或python中获取多个站的Netatmo数据
- html - 通过单击父级输入文本颜色
- java - Exoplayer - 在片段内旋转时保存和恢复状态
- node.js - node basic-auth - 在 URL 中传递基本身份验证凭据不起作用