在 Ballerina 中克隆常量映射后,字段访问的行为如何

问题描述 投票:0回答:1

考虑以下代码:

import ballerina/io;
type User record {|
    string name;
    string email;
|};

const USER = {
    name: "John Doe",
    email: "[email protected]"
};

public function main() {
    User user = USER.clone();
    user.name = "Jane Doe";
    io:println("User name: " + user.name);
}

这段代码正确吗?我有一张常量地图,并将其克隆为用户并更新了一个字段。由于它是具有常量映射的克隆,因此字段是否克隆为只读?那么 clone() 应该返回编译器错误,因为在目标类型中,该字段不是显式只读的,对吗?

目前由于此运行时错误而失败:

error: {ballerina/lang.map}InherentTypeViolation {"message":"cannot update 'readonly' field 'name' in record of type '(service:record {| "John Doe" name; "[email protected]" email; |} & readonly)'"}
But if I use cloneWithType() it is working fine:
public function main() returns error? {
    User user = check USER.cloneWithType();
    user.name = "Jane Doe";
    io:println("User name: " + user.name);
}

有人可以解释一下这里的行为吗?

clone readonly ballerina ballerina-swan-lake
1个回答
0
投票

这里 USER 的类型被推断为

{
    name: "John Doe",
    email: "[email protected]"
} & readonly

由 Ballerina 编译器生成。

USER.clone() 将返回类型为 的克隆记录

{
    name: "John Doe",
    email: "[email protected]"
} & readonly

(原值的类型)

该类型是 User 的子类型。因此编译器允许将其分配给用户变量。但克隆值是只读的。因为记录的原始类型是readonly 所以我们无法更新记录的字段。这就是错误消息的含义。

示例:- 假设有一种类型称为 A。

A & readonly a = value

A b = a

这里 b 的类型是 A & readonly 所以我们无法更新值 b 中的字段

但是如果你使用 CloneWithType 函数,它会克隆该值并将其转换为预期的类型。

所以这里用户的类型是User。

User user = check USER.cloneWithType();

所以我们可以更新这里的字段。

顺便说一句,重要的是要知道,当您使用带有不可变值的clone()(或cloneReadOnly())时,不会创建副本。值本身就是结果。

User user = USER.clone();
io:println(user == USER); // true

User & readonly userImmutable = USER.cloneReadOnly();
io:println(userImmutable == USER); // true
© www.soinside.com 2019 - 2024. All rights reserved.