官术网_书友最值得收藏!

There's more...

You might have noticed that for our example we really didn't need a length member and could have just calculated a length whenever we print. We use this pattern anyway, to illustrate the point of its usefulness in hiding implementations. Another good use for it is when the members of a struct themselves have their own constructors and one needs to cascade the constructor calls. This happens, for example, when we have a Vec as a member, as we will see later in the book, in the, Using a vector section in Chapter 2, Working with Collections.

Sometimes, your structs might need more than one way to initialize themselves. When this happens, try to still provide a new() method as your default way of construction and name the other options according to how they differ from the default. A good example of this is again vector, which not only provides a Vec::new() constructor but also a Vec::with_capacity(10), which initializes it with enough space for 10 items. More on that again in the Using a vector section in Chapter 2, Working with Collections.

When accepting a kind of string (either &str, that is, a borrowed string slice, or String, that is, an owned string) with plans to store it in your struct, like we do in our example, also considering a Cow. No, not the big milk animal friends. A Cow in Rust is a Clone On Write wrapper around a type, which means that it will try to borrow a type for as long as possible and only make an owned clone of the data when absolutely necessary, which happens at the first mutation. The practical effect of this is that, if we rewrote our NameLength struct in the following way, it would not care whether the called passed a &str or a String to it, and would instead try to work in the most efficient way possible:

use std::borrow::Cow;
struct NameLength<'a> {
name: Cow<'a, str>,
length: usize,
}

impl<'a> NameLength<'a> {
// The user doesn't need to setup length
// We do it for him!
fn new<S>(name: S) -> Self
where
S: Into<Cow<'a, str>>,
{
let name: Cow<'a, str> = name.into();
NameLength {
length: name.len(),
name,
}
}

fn print(&self) {
println!(
"The name '{}' is '{}' characters long",
self.name, self.length
);
}
}

If you want to read more about Cow, check out this easy-to-understand blog post by Joe Wilm: https://jwilm.io/blog/from-str-to-cow/.

The Into trait used in the Cow code is going to be explained in the Converting types into each other section in Chapter 5, Advanced Data Structures.

主站蜘蛛池模板: 凌云县| 河曲县| 昭苏县| 永兴县| 资源县| 磐安县| 凤翔县| 清苑县| 孝昌县| 嘉定区| 大城县| 连城县| 西城区| 云阳县| 怀安县| 乐东| 石屏县| 牙克石市| 贵港市| 红原县| 宿迁市| 丹寨县| 白城市| 腾冲县| 绵阳市| 贵州省| 五峰| 建昌县| 竹北市| 徐汇区| 吉安市| 北安市| 廊坊市| 南投市| 泸溪县| 三河市| 光山县| 安吉县| 大宁县| 酉阳| 肥乡县|