如何验证结构创建?

xeh*_*puk 2 validation struct rust

我正在通过示例研究Rust。我目前在TryFromTryInto。这是他们的代码:

struct EvenNumber(i32);

impl TryFrom<i32> for EvenNumber {
    type Error = ();

    fn try_from(value: i32) -> Result<Self, Self::Error> {
        if value % 2 == 0 {
            Ok(EvenNumber(value))
        } else {
            Err(())
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

该实现防止创建EvenNumber具有奇数的实例,但前提是我调用try_from(或try_into)。我仍然可以EvenNumber(1337)直接创建一个。

在 Java(和相关语言)中,可以验证构造函数内的实例创建,例如:

struct EvenNumber(i32);

impl TryFrom<i32> for EvenNumber {
    type Error = ();

    fn try_from(value: i32) -> Result<Self, Self::Error> {
        if value % 2 == 0 {
            Ok(EvenNumber(value))
        } else {
            Err(())
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如何在 Rust 中做到这一点?

kfe*_*v91 5

您将EvenNumber在某个模块内定义并保持其num字段私有,因此人们可以创建实例的唯一方法EvenNumber是通过您控制的公共方法,例如new. 例子:

mod some_mod {
    pub struct EvenNumber {
        num: i32,
    }
    
    impl EvenNumber {
        pub fn new(num: i32) -> Result<Self, ()> {
            if num % 2 == 0 {
                Ok(EvenNumber {
                    num,
                })
            } else {
                Err(())
            }
        }
    }
}

// bring EvenNumber into scope
use some_mod::EvenNumber;

fn try_to_create_invalid_even_number() -> EvenNumber {
    EvenNumber {
        num: 1337, // compile error
    }
}
Run Code Online (Sandbox Code Playgroud)

抛出:

error[E0451]: field `num` of struct `EvenNumber` is private
  --> src/lib.rs:24:9
   |
24 |         num: 1337,
   |         ^^^^^^^^^ private field
Run Code Online (Sandbox Code Playgroud)

操场


Ale*_*Sed 5

当您的元组结构体在不同的模块(可以只是不同的文件)中定义时或如下所示:

mod mod_name {
    #[derive(Debug)]
    pub struct EvenNumber(i32);
    
    use std::convert::TryFrom;
    impl TryFrom<i32> for EvenNumber {
        type Error = ();

        fn try_from(value: i32) -> Result<Self, Self::Error> {
            if value % 2 == 0 {
                Ok(EvenNumber(value))
            } else {
                Err(())
            }
        }
    }
}

fn main() {
    // let num = mod_name::EvenNumber(5); // error[E0603]: tuple struct constructor `EvenNumber` is private
    
    use std::convert::TryFrom;
    let num = mod_name::EvenNumber::try_from(4);
    println!("num = {:?}", num.unwrap());
}
Run Code Online (Sandbox Code Playgroud)

那么您将无法直接使用任何数字构造该元组。您可以通过取消注释上面示例中的注释行来测试这一点。在 Rust 中,实体的隐私仅对同级或父模块重要,但对相同作用域或子模块无关。