简体   繁体   English

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

[英]Why does Rust's documentation for methods use a separate builder struct as an example?

I was going through the struct and method docs and was wondering why the docs use this example: 我正在浏览结构和方法文档 ,并想知道为什么文档使用这个例子:

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

My slightly modified code is smaller and appears to do the exact same thing: 我稍微修改过的代码较小,看起来完全一样:

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

In general, a Circle and a CircleBuilder are not the same thing, so it makes sense to treat them as different types. 一般来说, CircleCircleBuilder不是一回事,因此将它们视为不同类型是有意义的。 In your example, once a Circle has been "finalized", there's actually nothing stopping someone from calling the builder methods ( x , y , radius ) - there's nothing enforcing it. 在你的例子中,一旦Circle被“敲定”,实际上没有什么能阻止某人调用构建器方法( xyradius ) - 没有什么可以强制执行它。 It may also be unclear to users which methods are for building, and which are for use on a constructed object. 用户还可能不清楚哪种方法用于构建,哪些方法用于构造的对象。 Rust has a type system which can be used to statically avoid mistakes like this - it makes sense to use it! Rust有一个类型系统,可以用来静态避免这样的错误 - 使用它是有道理的!

In other cases, the finalize step may be less trivial - eg opening files, doing other I/O, or calculating some other private fields (which wouldn't make sense to initialise when constructing the builder). 在其他情况下,最终化步骤可能不那么简单 - 例如打开文件,执行其他I / O或计算其他一些私有字段(在构建构建器时初始化是没有意义的)。

Note that the CircleBuilder impl contains only methods that can be chained together (they return a &mut CircleBuilder ), one that initializes and one that returns a Circle . 请注意, CircleBuilder impl仅包含可以链接在一起的方法(它们返回一个&mut CircleBuilder ),一个初始化,一个返回一个Circle

It makes sense when someone wants to create an object "incrementally", through multiple steps, and separate those methods from eg those exposing the object's properties. 当有人想要通过多个步骤“递增地”创建对象并将这些方法与例如暴露对象属性的方法分开时,这是有道理的。

Your code is fine - it's a matter of preference. 你的代码很好 - 这是一个偏好的问题。 I would probably only create a new(x: f64, y: f64, radius: f64) method that would build a full Circle at once, like Circle::new(1.0, 2.0, 2.0) . 我可能只会创建一个new(x: f64, y: f64, radius: f64)方法,它会立即构建一个完整的Circle ,如Circle::new(1.0, 2.0, 2.0) new(x: f64, y: f64, radius: f64) Circle::new(1.0, 2.0, 2.0)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM