Inheritance 协议类型对象的Swift数组
我有下一个遗产:Inheritance 协议类型对象的Swift数组,inheritance,swift,dynamic-linking,Inheritance,Swift,Dynamic Linking,我有下一个遗产: protocol P { var a : Int { get set } } class C : P { var a : Int ... } 然后我想创建一个通用数组,并通过一些操作对其进行迭代: class Main { var array : Array<Proto> var inst : Proto ... func foo() { array.append(C(a:10))
protocol P {
var a : Int { get set }
}
class C : P {
var a : Int
...
}
然后我想创建一个通用数组,并通过一些操作对其进行迭代:
class Main {
var array : Array<Proto>
var inst : Proto
...
func foo() {
array.append(C(a:10))
for obj in array {
obj.a = 20 //Error: Cannot assign to the result of this expression
}
inst = C(a:10)
inst.a = 20 //Works correctly
for var i = 0; i < arr.count; ++i {
inst = arr[i]
inst.a = 20 //No problem even here
}
}
}
主类{
变量数组:数组
var inst:Proto
...
func foo(){
数组.追加(C(a:10))
用于阵列中的obj{
obj.a=20//错误:无法分配到此表达式的结果
}
仪表=C(a:10)
仪表a=20//工作正常
对于变量i=0;i
如果我投:(obj为C)。a=20-那么一切都好。
有人能解释这种行为吗?问题是for-in循环不允许修改迭代项。从: 注 索引常量仅存在于循环范围内。如果要在循环完成后检查index的值,或者要将其值作为变量而不是常量使用,则必须在循环中使用它之前自己声明它 您可以尝试以下操作:
for obj in array {
var c = obj
c.a = 20 // This should work as c is a mutable copy of obj
}
补充:
请注意@ikuramedia所说的是正确的。上面的代码屏蔽了
obj
是值类型的情况,在这种情况下c
将是它的副本,数组中的值obj
实际上不会被修改。协议可以平等地应用于类、结构和枚举,因此在您的代码中编译器不能假定obj是对象类型。因此,它不知道obj是引用类型还是值类型。如果它是一个值类型,那么在没有变异方法的情况下,您无法更改对象,因此它假定您的代码类型不正确,并且无法编译
您可以将数组声明为符合Proto的AnyObject类型,也可以在for循环迭代器中向下转换:
for obj as!C在数组中
其他人已经描述了该问题-总结如下:
obj
是常量)
有两种方法可以解决此问题:
protocol P : class {
var a : Int { get set }
}
这将确保符合p
的任何对象必须是参考类型for i in indices(array) {
array[i].a = 20
}
现在,无论元素是值类型还是引用类型,我们都可以修改属性。但是,请注意,只有在修改元素的内容时,这种迭代才有效。插入和删除将使索引(数组)
返回的索引无效
此外,您必须注意确保在适当的位置修改内容。具体来说,当元素是值类型时,这样的代码实际上不会修改数组的内容:
for i in indices(array) {
var element = array[i]
element.a = 20
}
或者协议是
@class\u protocol
@ikuramedia:declar[ing]数组是符合Proto的任何对象的类型,你会怎么做?@senseve-事实上你是对的,我认为你不能直接声明它。您可以将协议声明为类协议,然后数组的类型符合该协议。或者,您可以声明符合协议的引用类型,并声明该类型的数组(但数组成员必须是该类型的实例)。很可能我会选择在循环中向下转换,让类型检查器确保我在数组中获得引用类型,然后在使用它们之前有条件地检查它们是否符合协议。这不是一个好的答案。最好确保我们有一个类类型。这个甚至不会崩溃。