结构体数据访问

我们已经看到了各种不同类型的结构体,包括对象结构体(具有 key 能力的)和非对象结构体(不具有 key 能力的)。 为了访问结构体实例的字段,无论是对象还是非对象,只需要使用点符号并调用 struct_instance.fieldstruct_instance 可以是一个可变或不可变的引用,或是一个值。然而,这在结构体定义模块之外是无效的:

module 0x123::a {
    public struct MyData has key {
        id: UID,
        value: u64,
    }
    
    // 这可行
    public fun get_value_from_reference(object: &MyData): u64 {
        object.value
    }
    
    // 这可行
    public fun get_value_from_mut_reference(object: &mut MyData): u64 {
        object.value
    }
}

module 0x123::b {
    use 0x123::a::MyData;
    
    // 这不可行
    public fun get_value(object: &MyData): u64 {
        object.value
    }
}

在上面的示例中,b::get_value 将无法编译,因为它试图访问 MyData 的 value 字段, 但 MyData 是在模块 a 中定义的,而不是在模块 b 中。在 Move 中,只有定义结构体的模块才能自由访问其字段。 如果其他模块需要访问某个字段,则需要通过原始模块的 getter 函数来访问:

module 0x123::b {
    use 0x123::a::MyData;
    
    // This now works
    public fun get_value(object: &MyData): u64 {
        a::get_value_from_reference(object)
    }
}

一般来说,这称为结构体数据访问的模块范围规则。这允许开发人员为其数据(结构体)的读取或写入定义规则。 他们可以将数据保密,不允许任何外部模块访问内部字段,或者他们可以实现公共 getter(返回内部字段的值)和 setter(设置内部字段的值), 这些函数可以被外部模块调用。他们还可以实现自定义认证模块,要求特定的权限对象才能更新结构体的值。

用户所有权规则

在第一门课程中,我们已经介绍了归属对象及其只能通过所有者发送的交易进行访问和修改。当交易执行时,这一点会被 Sui 区块链自动验证,并保证在未经许可的情况下,账户的归属对象不能被读取或修改。

通过执行这种所有权,用户可以放心,没有模块可以在未经他们明确签署授权交易的情况下读取或修改他们的归属对象。