编程Rust开发者

Rust中构造函数和与结构体相关的函数是如何工作的,new和with_capacity有什么区别?怎样正确实现它们?

用 Hintsage AI 助手通过面试

答案。

问题背景

在Rust中没有像面向对象语言中的经典构造函数,但有关联函数(通常是new),它们实现了通过显式初始化的构造函数模式。关联函数允许使用预设值创建结构的实例,或者使用附加逻辑(例如,提前分配内存)来创建它们。

问题

许多人只开始使用new,忘记了其他工厂方法的模式(例如,with_capacity),或者错误地实现了结构的初始化(特别是带有私有/公共字段的),这可能导致不变量错误。

解决方案

类型为new的关联函数通过impl实现,可能是创建满足不变量对象的唯一入口。像with_capacity这样的函数提供了额外的可能性,例如,提前分配内存。

代码示例:

pub struct MyBuffer { data: Vec<u8>, } impl MyBuffer { pub fn new() -> Self { MyBuffer { data: Vec::new() } } pub fn with_capacity(cap: usize) -> Self { MyBuffer { data: Vec::with_capacity(cap) } } }

关键特点:

  • 关联函数不接受self,作为静态方法工作
  • 公共工厂方法帮助设置不变量
  • 可以为不同的场景实现不同的“构造函数”

有陷阱的问题。

如果不实现new,Rust会默认生成它吗?

不。没有自动生成的new。如果方法没有明确实现,它将不存在,即使结构只有公共字段。

new和Default之间的根本区别是什么?

Default是一个特征构造函数,只能在类型实现或显式继承Default的地方被调用。它在泛型算法中是标准的,但不总是等同于new。

可以对私有结构使用new和with_capacity方法吗?

可以,方法可以设置为公共或私有,但为私有结构创建公共构造函数将不允许用户在模块外创建该结构的实例。

常见错误和反模式

  • 使所有结构字段都为公共,从而允许在构造函数外部创建不正确的值
  • 不为集合实现with_capacity,其中节省内存分配是重要的
  • 实现一个没有正确初始化所有字段的new

生活中的例子

消极案例

没有不变量的开放结构,所有字段都是公共的:

pub struct User { pub login: String, pub active: bool }

优点:

  • 轻松创建对象

缺点:

  • 可能会创建不正确的值(例如,空登录名,未初始化字段)

积极案例

字段私有,只能通过new创建,保证不变量:

pub struct User { login: String, active: bool } impl User { pub fn new(login: String) -> User { User { login, active: true } } }

优点:

  • 防止不正确的数据
  • 可以控制初始化的验证和逻辑

缺点:

  • 需要编写额外的方法——稍微更多的代码