在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
有一些对内部不可变数据的非所有者引用,利用这种不可变性...
6条答案
按热度按时间gkn4icbw1#
一个字段的不变性是不可能的。这是一个古老的version of Rust(想想0.8之前)中的选项,但它被放弃了,因为规则让很多人感到困惑。你可能会问,它是如何困惑的?这样想吧:如果一个字段被声明为可变的并且struct被声明为可变的并且所使用的引用是不可变引用(
&
),则该字段是_______
。Lily Ballard noted的最佳做法是,可以将
Shape
字段声明为private,并使用impl A {...}
创建一个getter方法。第一个
有一个命题可能会完全放弃可变性和不变性的概念(你不能说一个结构体永远不会改变)。
ryevplcw2#
你可以创建一个结构体,并且只为它实现Deref特性。如果没有DerefMut特性,就不可能改变包含的值。
https://doc.rust-lang.org/std/ops/trait.Deref.html
这样,编译器将使成员可用,就像它没有 Package 在另一个结构体中一样,不需要任何编写的getter方法调用。
第一个
cetgtptt3#
你不能强迫一个字段具有不变性。结构体在必要的时候如何改变它自己的值呢?
您可以做的是将字段设为private,并公开getter方法以返回对它的引用(或复制/克隆值)。
dgjrabp24#
一个解决方案可能是采用更通用的方法:
现在可以在每种情况下对每种其他类型使用不可变结构。
在模块中添加这个变量可以避免改变Immutable对象的内容。仍然可以通过一个新的Object覆盖它来改变保存Immutable对象本身的变量,但是你应该通过Immutable::new语句注意到它,这样你就可以避免使用它。
h4cxqtbf5#
在许多情况下,* 关联常数 * 可实现所需的行为:
当然,常量不能在创建时设置,它们在编译时设置。如果需要动态性,可以像其他答案中解释的那样将字段设置为私有。
pqwbnv8z6#
现在最简单的实现方法可能是使用多产开发者大卫Tolnay(
serde
和其他许多书的作者)的readonly crate。这个crate提供了一个属性宏来公开结构字段,这些字段在同一个模块内是可读和可写的,但只能在模块外可读。