methods - 为什么 Vec::len 是方法而不是公共(public)属性?

标签 methods rust visibility naming

我注意到 Rust 的 Vec::len 方法只是访问向量的 len 属性。为什么 len 不只是一个公共(public)属性,而不是围绕它包装一个方法?

我假设这是为了万一将来实现发生变化,不会有任何问题,因为 Vec::len 可以在没有任何 Vec< 用户的情况下改变它获取长度的方式 知道,但不知道还有没有别的原因。

我的问题的第二部分是关于我何时设计 API。如果我正在构建自己的 API,并且我有一个带有 len 属性的结构,我是否应该将 len 设为私有(private)并创建一个公共(public) len() 方法?在 Rust 中公开字段是不好的做法吗?我不这么认为,但我没有注意到在 Rust 中经常这样做。例如,我有以下结构:

pub struct Segment {
    pub dol_offset: u64,
    pub len: usize,
    pub loading_address: u64,
    pub seg_type: SegmentType,
    pub seg_num: u64,
}

这些字段中的任何一个是否应该是私有(private)的,而是像 Vec 那样具有包装函数?如果是这样,那为什么呢?在 Rust 中是否有一个好的指南可以遵循?

最佳答案

一个原因是为实现某种长度概念的所有容器提供相同的接口(interface)。 (例如 std::iter::ExactSizeIterator 。)

Vec的情况下, len()就像 setter/getter 一样:

impl<T> Vec<T> {
    pub fn len(&self) -> usize {
        self.len
    }
}

虽然这确保了整个标准库的一致性,但这种设计选择背后还有另一个原因......

这个 getter 防止外部修改 len .如果条件Vec::len <= Vec::buf::cap永远不会满足,Vec的方法可能会尝试非法访问内存。例如,执行 Vec::push :

pub fn push(&mut self, value: T) {
    if self.len == self.buf.cap() {
        self.buf.double();
    }
    unsafe {
        let end = self.as_mut_ptr().offset(self.len as isize);
        ptr::write(end, value);
        self.len += 1;
    }
}

将尝试写入超过容器拥有的内存的实际末端的内存。由于这一关键要求,对 len 的修改被禁止。


哲学

在库代码中使用这样的 getter 绝对是好事(疯狂的人可能会尝试修改它!)。

但是,人们应该以一种最大限度地减少对 getter/setter 的要求的方式来设计他们的代码。一个类应该尽可能地作用于它自己的成员。这些行动应该通过方法向公众公开。在这里,我指的是做有用事情 的方法——而不仅仅是返回/设置变量的普通 ol' getter/setter。尤其是 Setter 可以通过使用构造函数或方法变得多余。 Vec向我们展示了其中一些“ setter ”:

push
insert
pop
reserve
...

因此,Vec实现提供对外部世界的访问的算法。但它自己管理内部。

关于methods - 为什么 Vec::len 是方法而不是公共(public)属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50661775/

相关文章:

java - 为 customClass 列表定义方法

rust - 展平嵌套结构

javascript - Yii2 输入字段设置禁用取决于其他字段

jquery - 仅在可见时按 Enter 键使按钮可用

c# - 使 C# 方法 "implement"成为委托(delegate)

javascript - 在 Javascript 中使用 find 方法来堆叠数字

java - 类型为Printwriter的方法println(boolean)不适用于参数(void)

rust - 如何实现原子 32 位整数类型 AtomicU32?

rust - 返回多个异常的 Java 函数的 Rust 等效返回值是多少?

java - 如何设置文本框在框架中不可见