Class 方法在 Chapel 中接受派生 类

Class method accepting derived classes in Chapel

考虑以下代码,我希望将 class(此处为 Class2)及其派生的 classes(此处为 Class3)的实例存储在另一个 class 中的数组中(这里是 Class1)。如前所述,编译器对最后一行不满意。我做错了什么?

class Class2 {
    var y : int;
}

class Class3 : Class2 {
    var z : int;
}

class Class1 {
    var count : int;
    var x : [0..10] owned Class2?;

    proc add(ref a : Class2) {
        x[count] = a;
        count += 1;
    }
}

var C1 = new owned Class1();
var C2 = new owned Class2();
var C3 = new owned Class3();

C1.add(C2); // OK
C1.add(C3); // Compiler not happy

编译器输出:

test2.chpl:25: error: unresolved call 'owned Class1.add(owned Class3)'
test2.chpl:14: note: this candidate did not match: Class1.add(ref a: Class2)
test2.chpl:25: note: because call actual argument #1 with type owned Class3
test2.chpl:14: note: is passed to formal 'ref a: owned Class2'
$CHPL_HOME/modules/internal/Atomics.chpl:557: note: candidates are: AtomicT.add(value: T, param order: memoryOrder = memoryOrder.seqCst)
$CHPL_HOME/modules/internal/NetworkAtomics.chpl:280: note:                 RAtomicT.add(value: T, param order: memoryOrder = memoryOrder.seqCst)
note: and 4 other candidates, use --print-all-candidates to see them

尝试在 proc add 上使用 in 意图而不是 ref 意图:

class Class2 {
    var y : int;
}

class Class3 : Class2 {
    var z : int;
}

class Class1 {
    var count : int;
    var x : [0..10] owned Class2?;

    proc add(in a : Class2) {
        x[count] = a;
        count += 1;
    }
}

var C1 = new owned Class1();
var C2 = new owned Class2();
var C3 = new owned Class3();

C1.add(C2); // OK
C1.add(C3); // OK!

为什么这很重要?将对子 class (Class3) 的引用传递给期望对父 class (Class2) 的引用的参数不是类型安全的。特别是您可以想象将 class 指针更改为 Class2 而不是 Class3 的方法,这可能会导致调用站点出现其他错误。

我的猜测是 add 函数使用 ref 意图只是为了实现从 C3 的所有权转移。 in intent 是一种更好的方法,它支持传递子类型(因为上述类型错误情况是不可能发生的)。