Add the extensibility by privacy pattern

(And change the concatenation pattern to say something different about perf)
pull/25/head
Nick Cameron 9 years ago
parent e708788268
commit 6ac851e718

@ -12,7 +12,7 @@ language.
* [Constructor](idioms/ctor.md)
* [Concatenating strings with `format!`](idioms/concat-format.md)
* TODO private field to indicate extensibility
* [Privacy for extensibility](idioms/priv-extend.md)
* TODO trait to separate visibility of methods from visibility of data (https://github.com/sfackler/rust-postgres/blob/master/src/lib.rs#L1400)
* [Collections are smart pointers](idioms/deref.md)
* TODO leak amplification ("Vec::drain sets the Vec's len to 0 prematurely so that mem::forgetting Drain "only" mem::forgets more stuff. instead of exposing uninitialized memory or having to update the len on every iteration")

@ -27,4 +27,9 @@ fn say_hello(name: &str) -> String {
## Advantages
Using `format!` is usually the most succinct and readable way to combine strings.
In nearly all cases it will generate optimal code in terms of performance too.
## Disadvantages
It is usually not the most efficient way to combine strings - a series of `push`
operations on a mutable string is usually the most efficient (especially if the
string has been pre-allocated to the expected size).

@ -0,0 +1,35 @@
# Privacy for extensibility
## Description
Use a private field to ensure that a struct is extensible without breaking
stability guarantees.
## Example
```rust
mod a {
// Public struct.
pub struct S {
pub foo: i32,
// Private field.
bar: i32,
}
}
fn main(s: a::S) {
// Because S::bar is private, it cannot be named here and we must use `..`
// in the pattern.
let a::S { foo: _, ..} = s;
}
```
## Discussion
Adding a field to a struct is a mostly backwards compatible change. However, if a client uses a pattern to deconstruct a struct instance, they might name all the fields in the struct and adding a new one would break that pattern. The client could name some of the fields and use `..` in the pattern, in which case adding another field is backwards compatible. Making at least one of the struct's fields private forces clients to use the latter form of patterns, ensuring that the struct is future-proof.
The downside of this approach is that you might need to add an otherwise unneeded field to the struct. You can use the `()` type so that there is no runtime overhead and can add the annotation `#[allow(dead_code)]` to the struct to avoid the unused field warning.
If Rust allowed private variants of enums, we could use the same trick to make adding a variant to an enum backwards compatible. The problem there is exhaustive match expressions. A private variant would force clients to have a `_` wildcard pattern.
Loading…
Cancel
Save