Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[idioms/ctor] adds default constructor section #280

Merged
Next Next commit
[idioms/ctor] adds default constructor section
First, I replaced the `Vec` example with `Second`. This is easier to
comprehend compared to the more complex `Vec` example. It's also
testable because it doesn't rely on `RawVec`.
  • Loading branch information
wookietreiber committed Oct 17, 2021
commit ca0207de986b45a779260686d8e50033408d70e4
90 changes: 65 additions & 25 deletions idioms/ctor.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,74 @@
## Description

Rust does not have constructors as a language construct. Instead, the
convention is to use a static `new` method to create an object.

## Example

```rust,ignore
// A Rust vector, see liballoc/vec.rs
pub struct Vec<T> {
buf: RawVec<T>,
len: usize,
}

impl<T> Vec<T> {
// Constructs a new, empty `Vec<T>`.
// Note this is a static method - no self.
// This constructor doesn't take any arguments, but some might in order to
// properly initialise an object
pub fn new() -> Vec<T> {
// Create a new Vec with fields properly initialised.
Vec {
// Note that here we are calling RawVec's constructor.
buf: RawVec::new(),
len: 0,
}
convention is to use an associated `new` function to create an object:

```rust
pub struct Second {
value: u64
}

impl Second {
pub fn new(value: u64) -> Self {
simonsan marked this conversation as resolved.
Show resolved Hide resolved
Self { value }
}
}

fn main() {
let s = Second::new(42);
}
```

## Default Constructors

Rust supports default constructors with the [`Default`][std-default] trait:

```rust
pub struct Second {
value: u64
}

impl Default for Second {
fn default() -> Self {
Self { value: 0 }
}
}

fn main() {
let default = Second::default();
simonsan marked this conversation as resolved.
Show resolved Hide resolved
assert_eq!(default.value, 0);
}
```

`Default` can also be derived if all types of all fields implement `Default`,
like they do with `Second`:

```rust
#[derive(Default)]
pub struct Second {
value: u64
}

fn main() {
let default = Second::default();
assert_eq!(default.value, 0);
}
```

**Note:** When implementing `Default` for a type, it is neither required nor
recommended to also provide an associated `new` function without arguments.

**Hint:** The advantage of implementing or deriving `Default` is that your type
can now be used where a `Default` implementation is required, most prominently,
any of the [`*or_default` functions in the standard library][std-or-default].

## See also

The [builder pattern](../patterns/creational/builder.md) for constructing objects
where there are multiple configurations.
- The [default idiom](default.md) for a more in-depth description of the
`Default` trait.

- The [builder pattern](../patterns/creational/builder.md) for constructing
objects where there are multiple configurations.

[std-default]: https://doc.rust-lang.org/stable/std/default/trait.Default.html
[std-or-default]: https://doc.rust-lang.org/stable/std/?search=or_default