在 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)'"}

但是如果我使用cloneWithType()它工作正常:

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个回答
1
投票

这里 USER 的类型被推断为

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

由 Ballerina 编译器生成。

USER.clone() 将返回

USER
记录本身,因为它是不可变的。

因此,USER 的类型是

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

示例:- 假设有一种类型称为 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.