【一起学Rust | 设计模式】习惯语法——使用借用类型作为参数、格式化拼接字符串、构造函数

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

Rust 不是传统的面向对象编程语言,它的所有特性,使其独一无二。因此,学习特定于Rust的设计模式是必要的。本系列文章为作者学习《Rust设计模式》的学习笔记以及自己的见解。因此,本系列文章的结构也与此书的结构相同(后续可能会调成结构),基本上分为三个部分

  1. 习惯语法
  2. 设计模式
  3. 反模式(anti_patterns)

习惯语法是社区广泛认同的Rust编程常用风格、指导方针和模式。编写惯用的代码可以让其他开发人员更好地理解你所写的代码。

本期文章是该系列文章的开篇内容,从Rust的惯用程序设计手法来入门学习,与设计模式的书所对应,即本期主题为

  1. 使用借用类型作为参数
  2. 格式化字符串
  3. 构造函数

一、使用借用类型作为参数

使用借用类型作为参数可以避免函数传参过程中的间接层,就比如String有一个间接层,&String就有两个间接层,我们可以通过使用&str来避免这种情况,并让&String在调用函数时强制转换为&str。

在本例中,我们使用&String来作为函数参数与&str进行对比。

这种情况在 &Vec<T>&[T] 或者 &Box<T>&T 上也适用。

借用书中的例子,比如说我们想要判断一个单词中是否有三个元音,我们使用&String作为参数传入,代码就应该写成下面这样

元音:a e i o u

fn three_vowels(word: &String) -> bool {
    
    
    let mut vowel_count = 0;
    for c in word.chars() {
    
    
        match c {
    
    
            'a' | 'e' | 'i' | 'o' | 'u' => {
    
    
                vowel_count += 1;
                if vowel_count >= 3 {
    
    
                    return true
                }
            }
            _ => vowel_count = 0
        }
    }
    false
}

fn main() {
    
    
    let ferris = "Ferris".to_string();
    let curious = "Curious".to_string();
    println!("{}: {}", ferris, three_vowels(&ferris));
    println!("{}: {}", curious, three_vowels(&curious));

    // 上面这么写是没有问题的,但是如果写成下面注释里面的样子,就会报错
    // println!("Ferris: {}", three_vowels("Ferris"));
    // println!("Curious: {}", three_vowels("Curious"));

}

这种情况在C++里面也是十分常见的,因为函数签名里面传入的参数类型应该是&String,如果直接传入"Ferris",则是&str,它在传入函数中的时候,不会强制转化为&String,这点学习C++的朋友一定特别熟悉,如果要使之可以那样传参,那么函数签名就得这么改

fn three_vowels(word: &str) -> bool {
    
    

这样不论我们传的是哪种参数,就都会输出正常的结果

Ferris: false
Curious: true

现在我们尝试这样一个例子,给出一个句子,判断其中每一个单词,是否有三个联系的元音字母,为此,我们把代码改成如下的样子

fn three_vowels(word: &str) -> bool {
    
    
    let mut vowel_count = 0;
    for c in word.chars() {
    
    
        match c {
    
    
            'a' | 'e' | 'i' | 'o' | 'u' => {
    
    
                vowel_count += 1;
                if vowel_count >= 3 {
    
    
                    return true
                }
            }
            _ => vowel_count = 0
        }
    }
    false
}

fn main() {
    
    
    let sentence_string =
        "Once upon a time, there was a friendly curious crab named Ferris".to_string();
    for word in sentence_string.split(' ') {
    
    
        if three_vowels(word) {
    
    
            println!("{} 有三个连续的元音!", word);
        }
    }
}

可以看到,three_vowels函数我们并未改变,而是在调用函数的地方,使用split方法,将字符串分割为多个单词,依次传入函数,此时就体现出&str的好处了,split返回的数组中的元素都是&str类型的。而String类型转&str就很简便。

二、格式化拼接字符串

一般来说,我们在开发的时候,做字符串拼接会使用String方法的push和push_str方法,或者直接就用+来实现字符串的拼接,但是有时候使用format!可能会更加的方便,特别是混合了各种类型的东西的字符串。

首先我们手动的构建一个字符串

let mut hello = "Hello ".to_owned();
hello.push_str(name);
hello.push('!');

这是相当常见的一种用法,现在我们使用格式化的方式来构建这个字符串

fn say_hello(name: &str) -> String {
    
    
    format!("Hello {}!", name)
}

format!返回一个格式化的字符串,{}作为占位符,然后后面传入参数,就可以返回处理好的字符串了,在这么一个简单的地方难以看出他的好处,但是当插入的东西比较多的时候就知道格式化字符串的好处了。

这一块在python和js中都有类似的东西,我觉得还是python和js里面的好用在js里面只需要
let hello = `hello ${name}`

在Rust中,使用format!来格式化拼接字符串是最简洁、可读性最好的方法。

三、使用构造函数

在Rust中实际上是没有构造函数这个概念的,但是可以使用一个约定俗成的关联函数new来创建一个对象。就比如

pub struct Second {
    
    
    value: u64
}

impl Second {
    
    
    // 构建一个Second实例
    // 注意,这是个关联函数,参数里面没有self
    pub fn new(value: u64) -> Self {
    
    
        Self {
    
     value }
    }

    /// 返回秒数,即Second的value
    pub fn value(&self) -> u64 {
    
    
        self.value
    }
}

我们创建了个Second 结构体,并且实现了new方法来构建一个新的对象。

在使用的时候,我们调用new方法就可以创建一个对象了

let s = Second::new(42);

Rust中还可以实现Default特质来实现默认的构造方法

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

使用derive派生Default也能起到同样的效果,比如你可以这么写

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

impl Second {
    
    
    pub fn value(&self) -> u64 {
    
    
        self.value
    }
}

此时我们不用new方法了,可以直接调用default方法来构建实例

let s = Second::default();

注意: 这里更推荐你使用new来创建构造方法,在社区的开发中,通常会使用new来实现构造方法,因为它比起default更加合理,也更加符合阅读习惯,他的功能的default是一样的。


总结

本节内容为Rust设计模式的第一期,主要为大家引入了Rust设计模式的一些惯用语法,学习了

  • 使用借用类型作为函数参数
  • 格式化拼接字符串
  • 构造函数

相信通过本系列文章,你可以对Rust有更加深入的理解。


本人创建了一起学Rust社区,欢迎各位对rust感兴趣的朋友加入

 http://t.csdn.cn/AsEZ9 

猜你喜欢

转载自blog.csdn.net/weixin_47754149/article/details/126571097