Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Inheritance 协议类型对象的Swift数组_Inheritance_Swift_Dynamic Linking - Fatal编程技术网

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-事实上你是对的,我认为你不能直接声明它。您可以将协议声明为类协议,然后数组的类型符合该协议。或者,您可以声明符合协议的引用类型,并声明该类型的数组(但数组成员必须是该类型的实例)。很可能我会选择在循环中向下转换,让类型检查器确保我在数组中获得引用类型,然后在使用它们之前有条件地检查它们是否符合协议。这不是一个好的答案。最好确保我们有一个类类型。这个甚至不会崩溃。