如何强制struct的字段在Rust中始终是不可变的?

问题描述 投票:6回答:2

在Rust中,您没有在struct中指定可变性,但它是从变量绑定继承的。这很好,但是有可能强制一个字段总是不可变的,即使根是可变的吗?

像这个假设的语法:

struct A {
    immut s: Shape, // immutable by design
    bla: Bla, // this field inheriting (im)mutability
}
let mut a = make_a();
a.s = x/*...*/; // illegal

这将有助于在程序中保持良好的语义限制,就像Java的final一样(以非常有限的方式)。

此外,我们可以想象这种struct对内部不可变数据有一些非拥有的引用,利用这种不变性......

immutability rust
2个回答
4
投票

单个领域的不可变性是不可能的。这是一个古老的version of Rust(在0.8之前考虑)的一个选项,但它被删除,因为规则混淆了很多人。你可能会问,这有多令人困惑?想想这样:如果一个字段被声明为可变并且struct被声明为可变并且所使用的引用是一个不可变引用(&),那么该字段是_______

最好的,就像Lily Ballard noted一样,你可以将你的Shape字段声明为私有,并使用impl A {...}制作一个getter方法。

mod inner {
    pub struct A {
        s: i32, // can't be seen outside of module
        pub bla: i32,
    }

    impl A {
        pub fn new() -> Self {
            Self { s: 0, bla: 42 }
        }

        pub fn get_s(&self) -> i32 {
            self.s
        }
    }
}
let mut a = inner::A::new();
a.s = 42; // illegal
println!("{}", a.s); // also illegal
println!("{}", a.get_s()); // could be made to serve as a read-only method
error[E0616]: field `s` of struct `main::inner::A` is private
  --> src/main.rs:20:5
   |
20 |     a.s = 42; // illegal
   |     ^^^

error[E0616]: field `s` of struct `main::inner::A` is private
  --> src/main.rs:21:20
   |
21 |     println!("{}", a.s); // also illegal
   |                    ^^^

有一个命题可能会完全忽略可变性和不变性的概念(你不能说结构永远不会改变)。请参阅Niko's explanation了解该更改。


3
投票

你不能强迫场上的不变性。结构如何在必要时改变自己的值?

你可以做的是使该字段为私有,并公开一个getter方法来返回对它的引用(或复制/克隆该值)。

© www.soinside.com 2019 - 2024. All rights reserved.