为什么Rust的方法文档使用单独的构建器结构作为示例?

时间:2016-09-02 11:03:42

标签: rust

我正在浏览struct and method docs,并想知道为什么文档会使用这个例子:

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);
}

我稍微修改过的代码较小,看起来完全一样:

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


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

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

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

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

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

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

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

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

2 个答案:

答案 0 :(得分:5)

一般来说,CircleCircleBuilder不是一回事,因此将它们视为不同类型是有意义的。在您的示例中,一旦Circle已经完成",实际上并没有阻止某人调用构建器方法(xy,{ {1}}) - 没有任何强制执行。用户还可能不清楚哪种方法用于构建,哪些方法用于构造的对象。 Rust有一个类型系统,可以用来静态避免这样的错误 - 使用它是有道理的!

在其他情况下,最终确定步骤可能不那么重要 - 例如打开文件,执行其他I / O或计算其他一些私有字段(在构建构建器时初始化是没有意义的。)

答案 1 :(得分:1)

请注意,CircleBuilder impl仅包含可以链接在一起的方法(它们返回&mut CircleBuilder),一个初始化,另一个返回Circle

当有人想要通过多个步骤逐步创建一个对象并将这些方法与例如这些方法分开时,这是有意义的。暴露对象属性的那些。

您的代码很好 - 这是一个偏好问题。我可能只会创建一个new(x: f64, y: f64, radius: f64)方法,可以同时构建一个完整的Circle,例如Circle::new(1.0, 2.0, 2.0)