如何强制在Rust中将结构的字段始终保持不变? [英] How can I force a struct's field to always be immutable in Rust?

查看:64
本文介绍了如何强制在Rust中将结构的字段始终保持不变?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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利用内部不可变性对内部不可变数据具有一些非所有权引用...

解决方案

不可能具有单个字段的不变性.这是古代 Rust版本的选择(在0.8之前考虑),但由于规则使很多人感到困惑,因此将其删除.您可能会问,这令人困惑吗?像这样思考:如果一个字段被声明为可变的,而struct被声明为可变的,并且使用的引用是一个不可变的引用(&),则该字段为_______.

莉莉·巴拉德(Lily Ballard)所述,最好的做法是,您可以将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的解释.

In Rust, you don't specify mutability inside a struct, but it is inherited from the variable binding. That's great, but is it possible to force a field to be always immutable, even when the root is mutable?

Something like this hypothetical syntax:

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

This would help to maintain nice semantic restrictions in a program, just like Java's final does (in a very limited way).

Also, we could imagine this kind of struct having some non-owning references to internal immutable data, taking advantage of this immutability...

解决方案

It's impossible to have immutability of a single field. That was an option in an ancient version of Rust (think before 0.8), but it was dropped because the rules confused a LOT of people. How was it confusing, you might ask? Think about it like this: if a field is declared mutable and struct is declared mutable and the reference used was an immutable reference (&) then the field is _______.

The best, as Lily Ballard noted, is that you can declare your Shape field as private and make a getter method using impl A {...}.

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
   |                    ^^^

There is proposition that might drop notions of mutability and immutability completely (you can't say a struct never changes). See Niko's explanation for that change.

这篇关于如何强制在Rust中将结构的字段始终保持不变?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆