【问题标题】:Rust disable struct constructionRust 禁用结构构造
【发布时间】:2022-01-15 16:51:11
【问题描述】:

如何在 Rust 中禁用结构构造但保持模式匹配?

我们来看一个例子:

struct OrderedPair(pub u32, pub u32);

impl OrderedPair {
    fn new(a: u32, b: u32) -> Self {
        if a < b {
            Self(a, b)
        } else {
            Self(b, a)
        }
    }
}

很明显,我想禁止构造此类结构(例如OrderedPair(2, 1))并仅使用new 方法,以保留不变量。我知道 3 种方法可以做到这一点:

  1. 将字段设为私有
struct OrderedPair(u32, u32);
  1. 添加私有虚拟字段
struct OrderedPair(pub u32, pub u32, ());
  1. 使结构不详尽
#[non_exhaustive]
struct OrderedPair(pub u32, pub u32);

问题是 1 我根本无法访问成员,而所有三个我都无法使用模式匹配

let OrderedPair(min, max) = my_ordered_pair;

那么有没有办法阻止结构构造但允许模式匹配?

我知道,如果我们声明一个具有对成员的公共访问权限的该类型的可变变量,那么可以通过手动更改成员来破坏不变量,但现在避免使用 struct 构造函数就足够了。

【问题讨论】:

    标签: struct rust constructor pattern-matching


    【解决方案1】:

    您可以对返回的元组进行模式匹配,而不是直接在字段上进行模式匹配:

    #[derive(Clone, Copy)]
    pub struct OrderedPair {
        a: u32,
        b: u32,
    }
    impl OrderedPair {
        pub fn new(a: u32, b: u32) -> Self {
            let (a, b) = if a < b { (a, b) } else { (b, a) };
            Self { a, b }
        }
        pub fn content(self) -> (u32, u32) {
            (self.a, self.b)
        }
    }
    

    【讨论】:

    • 有趣,我从来没想过。这可能是一个非常好的妥协。
    • 如果你实现 Deref (to pair) trait 会有帮助吗?
    • @hkBst 不。不要。来自the documentation:“只应为智能指针实现 Deref 以避免混淆”。这是一个非常中肯的建议。
    • 这让我考虑这是否是一个智能指针;p... 更严肃的一点是:您是否有一些指针会造成混淆?
    • @hkBst 你不觉得当你在迭代器链的中间使用 *x 并且你没有得到你的 OrderedPair 而是一个元组时会有点不清楚吗?当有更多,或者你需要应用函数但你没有 OrderedPair 而是一个元组时会发生什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 2010-09-08
    • 2016-05-10
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多