Метод класса, принимающий производные классы в часовне - PullRequest
3 голосов
/ 07 ноября 2019

Рассмотрим следующий код, в котором я хочу хранить экземпляры класса (здесь Class2) и его производных классов (здесь Class3) в массиве, находящемся в другом классе (здесь 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

1 Ответ

4 голосов
/ 07 ноября 2019

Попробуйте использовать in вместо ref на proc add:

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!

Почему это важно? Передача ссылки на подкласс (Class3) в аргумент, ожидающий ссылку на родительский класс (Class2), небезопасна. В частности, вы можете себе представить, что метод изменяет указатель класса на Class2, а не Class3, и это может привести к другим ошибкам на сайте вызова.

Я предполагаю, что функция add использовала функциюref Намерение просто включить передачу права собственности от C3. Намерение in является лучшим способом сделать это и поддерживает передачу подтипа (поскольку описанная выше ситуация с ошибкой типа невозможна).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...