【问题标题】:Constraint value for Rust typesRust 类型的约束值
【发布时间】:2021-04-21 08:06:41
【问题描述】:

在 Rust 中,是否可以为类型定义约束?
类似于数据库中的约束。

示例:具有只能分配有效电子邮件的电子邮件类型
示例:具有只能分配 "male""female" 的性别类型

更清楚的例子:

type email = string;
/// Do something here to constrain the type to only accept valid emails assigned to it.

let my_mail:  email = "something@domain.com"  // -> OK
let my_mail2: email = "something"  // -> Error

我想知道这是否不仅适用于结构成员。

【问题讨论】:

  • 您可以定义一个函数fn set_mail(mail: &str) -> Result<(), ()>,如果它不符合您的要求则返回错误?不过我不明白你的问题。
  • 还是使用只能通过检查值的方法访问的newtype?
  • 注意:对于第二个例子,enums 就是这样做的。
  • @Jmb 创建一个函数似乎是我正在寻找的,它类似于基于类的语言中的设置器。

标签: variables types rust constraints assign


【解决方案1】:

您可以通过围绕基本类型定义包装器并在实例化包装器时检查您的要求来做到这一点。

对于电子邮件地址,示例可能是:

pub struct Email<'a>{
    // Private by default, so no one can access or edit it
    address: &'a str
};

impl<'a> Email<'a>
{
    pub fn new(address: &'a str) -> Result<Self, ()>
    {
        if is_valid_email(address) {
            Ok(Self{address})
        } else {
            Err(()) // Invalid email address
        }
    }

    // Provides read-only access to the raw address.
    pub fn get_address(&self) -> &'a str
    {
        self.address
    }
}

然后,在您需要有效电子邮件的任何地方,您只需将Email 作为参数,确信没有人可以使用无效地址创建Email

【讨论】:

  • 您甚至可以实现Deref&lt;Target = &amp;'a str&gt;,以便可以在任何需要(非可变)字符串的地方使用&amp;email
  • 没有结构也可以做到这一点吗?
  • 你可以做一些类似于枚举的事情或使用元组结构(struct Email&lt;'a&gt;(&amp;'a str))。但是,如果您希望类型系统确保您收到有效的电子邮件,则无法真正绕过将 str 包装起来。
  • 我在操场上尝试了您的示例代码,但它似乎没有按预期工作play.rust-lang.org/… 我以为Err 上的电子邮件将是空的。
  • 您必须使用Email::new("test") 来检查电子邮件是否有效:playground。然后它将返回Err(()),这意味着您没有有效的电子邮件。如果您直接实例化结构 (Email{address="test"}),则您正在绕过检查。当我说没有人可以创建不包括您的无效Email 时,因为您可以完全控制对结构执行任何操作,包括验证无效电子邮件。
【解决方案2】:

有一个板条箱可以对结构进行验证:https://github.com/Keats/validator

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-21
    • 2012-09-06
    • 1970-01-01
    • 2012-01-06
    相关资源
    最近更新 更多