用于暴露公共字段同时限制直接结构构造的 Rust 习惯用法

Jim*_*Jim 1 constructor visibility rust

我知道 Rust 中的可见性规则和 Rust 中典型的“构造函数”模式,例如通过关联函数,通常命名为new或如果结构的所有字段都是公共的,则通过“直接”构造,例如Struct {value: 0}

只是希望了解实现以下目标的适当习惯用法是什么:

公开具有所有公共字段的公共结构,但限制直接构建。

例如

pub struct MyStruct {
    pub val: u8,
}

impl MyStruct {
    pub fn new(val: u8) {
        MyStruct {val}
    }
}
Run Code Online (Sandbox Code Playgroud)

外部板条箱可以执行此操作:

use your_crate::MyStruct;

let your_struct = MyStruct::new(8);
println!("{}", your_struct.val);
//8
Run Code Online (Sandbox Code Playgroud)

但对于外部板条箱(将其称为“your_crate”与其中MyStruct定义的“my_crate”)来说不行:

use my_crate::MyStruct;

let your_struct = MyStruct {val: 8};
// above should return compile error
Run Code Online (Sandbox Code Playgroud)

我知道有两种方法可以实现这一目标。

  1. 使用getterandsetter方法并将字段设为私有。
pub struct MyStruct {
    val: u8,
}

impl MyStruct {
    pub fn new(val: u8) {
        MyStruct {val}
    }

    pub fn get_val(&self) -> &u8 {
        self.val
    }
    
    pub fn set_val(&mut self, new_val: u8) {
        *self.val = new_val;
    }
}
Run Code Online (Sandbox Code Playgroud)

这通过方法调用而不是属性访问来间接提供对字段的访问。

  1. 添加一个“私有”无关紧要的字段。
pub struct MyStruct {
    pub val: u8,
    _private: (),
}
Run Code Online (Sandbox Code Playgroud)

这可以防止直接构造,但允许直接属性访问,并且无需实现多余的“get”和“set”方法。

我的问题是:

哪个成语更适合社区中的许多人接受?或者,图书馆作者在决定哪种习惯用法更合适之前应该考虑哪些因素?

Mas*_*inn 9

您可以使用私有字段技巧,但执行此操作的正常方法可能是注释#[non_exhaustive],它适用于结构和枚举。

非详尽类型不能在定义包之外构造:

  • 非详尽的变体(structenum变体)不能用 a 构造StructExpression(包括使用功能更新语法)。