gpt4 book ai didi

struct - Rust 构建器模式是否必须使用冗余结构代码?

转载 作者:行者123 更新时间:2023-11-29 08:05:10 27 4
gpt4 key购买 nike

我正在查看 Method syntax section of the Rust documentation并遇到了构建器模式的示例。下面示例中的 CircleBuilder 结构与 Circle 结构完全相同。这段冗余代码似乎违反了通常的编程规范。

我明白为什么这个例子创建了一个新的结构,因为创建者不想针对原始的 Circle 结构实现构建器方法。这很好,但是有没有一种方法可以重写此示例以便没有冗余——同时仍然保持 main() 函数中漂亮的构建器界面完好无损?

我试图创建一个空结构或仅包含一个一次性元素的结构,但这没有用。

struct Circle {
x: f64,
y: f64,
radius: f64,
}

impl Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}

struct CircleBuilder {
x: f64,
y: f64,
radius: f64,
}

impl CircleBuilder {
fn new() -> CircleBuilder {
CircleBuilder { x: 0.0, y: 0.0, radius: 1.0, }
}

fn x(&mut self, coordinate: f64) -> &mut CircleBuilder {
self.x = coordinate;
self
}

fn y(&mut self, coordinate: f64) -> &mut CircleBuilder {
self.y = coordinate;
self
}

fn radius(&mut self, radius: f64) -> &mut CircleBuilder {
self.radius = radius;
self
}

fn finalize(&self) -> Circle {
Circle { x: self.x, y: self.y, radius: self.radius }
}
}

fn main() {
let c = CircleBuilder::new()
.x(1.0)
.y(2.0)
.radius(2.0)
.finalize();

println!("area: {}", c.area());
println!("x: {}", c.x);
println!("y: {}", c.y);
}

最佳答案

Do Rust builder patterns have to use redundant struct code?

没有。但有时他们可能。例如,考虑一下我们是否希望在我们的构造函数周围有特殊的逻辑(或者甚至只是复杂的逻辑):

/// Width must always be greater than height!
struct HorizontalEllipse {
width: f64,
height: f64,
}

impl HorizontalEllipse {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.width / 2.0) * (self.height / 2.0)
}
}

struct HorizontalEllipseBuilder {
width: f64,
height: f64,
}

impl HorizontalEllipseBuilder {
fn new() -> HorizontalEllipseBuilder {
HorizontalEllipseBuilder {
width: 0.0,
height: 0.0,
}
}

fn width(&mut self, width: f64) -> &mut HorizontalEllipseBuilder {
self.width = width;
self
}

fn height(&mut self, height: f64) -> &mut HorizontalEllipseBuilder {
self.height = height;
self
}

fn finalize(&self) -> Result<HorizontalEllipse, String> {
let HorizontalEllipseBuilder { height, width } = *self;
if height >= width {
Err("This is not horizontal".into())
} else {
Ok(HorizontalEllipse { width, height })
}
}
}

fn main() {
let c = HorizontalEllipseBuilder::new()
.width(1.0)
.height(2.0)
.finalize()
.expect("not a valid ellipse");

println!("area: {}", c.area());
println!("width: {}", c.width);
println!("height: {}", c.height);
}

现在 Horizo​​ntalEllipse 知道 width > height 始终为真。我们已将该检查从许多可能的地方(每个方法)移到一个地方,即构造函数。然后我们将构造函数移动到一个新类型,因为它很复杂(不是真的,但真正复杂的例子通常……很复杂)。

我见过的许多构建器还具有真实对象的“增强”类型:

#[derive(Debug)]
struct Person {
name: String,
}

#[derive(Debug, Default)]
struct PersonBuilder {
name: Option<String>,
}

impl PersonBuilder {
fn name(self, name: &str) -> Self {
PersonBuilder { name: Some(name.into()), ..self }
}

fn build(self) -> Person {
Person {
name: self.name.unwrap_or_else(|| "Stefani Joanne Angelina Germanotta".into()),
}
}
}

fn main() {
let person = PersonBuilder::default().build();
println!("{:?}", person);

let person = PersonBuilder::default().name("krishnab").build();
println!("{:?}", person);
}

您在本书的示例中看不到这一点,因为它试图变得更简单并且不涉及所有权问题。

关于struct - Rust 构建器模式是否必须使用冗余结构代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43840415/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com