每一种编程语言都有高效处理重复概念的工具,Rust使用的是泛型。泛型是具体类型或其它抽象类型的替代。我们可以表达泛型的属性,比如他们的行为如何与其它类型的泛型相关联,而不许需要在编写或者编译代码时知道它们在这里实际上代表的是什么
我们编写一个函数,想让它对多种类型的参数都具有处理能力,而不仅仅是针对某种具体类型的参数定义函数。这个时候我们就可以指定函数的参数类型是泛型,而不是某种具体类型。我们之前使用了Option、Vec!和HashMap
提取函数来减少重复
在此之前,我们先来回顾一个不使用泛型就解决代码重复的技术,提取函数
fn main() {
let number_list = vec![34,25,50,100,65];
let mut largest = number_list[0];
for number in number_list {
if number > largest {
largest = number
};
};
println!("the largest number is {}",largest)
}
我们先遍历了一个vector,求其元素的最大值,那如果我们要遍历另一个元素的话,就需要再重复一下这些代码,现在我们用函数来做个提取
fn largest(list:&[i32])->i32{
let mut largest = list[0];
for &item in list {
if item > largest {
largest = item
};
};
largest
}
fn main(){
let number_list = vec![34,50,25,100,65];
let result = largest(&number_list);
println!("{}",result)
}
通过函数抽象,我们就不用再重用代码了,只需要调用这个比较逻辑(我们新定义好的函数)即可
但是!我们在这里寻找的是vec中的最大值,如果我们要寻找char、slice中的最大值呢?下面我们来着手解决这个问题
trait告诉编译器某个特定的类型可能拥有与其他了类型共享的功能。因此我们可以使用trait来抽象定义一组共享的行为,trait有点像其它语言中的接口。可以使用trait bounds指定泛型是任何拥有特定行为的类型
定义trait
一个类型的行为由其可供调用的方法构成,如果不同的类型可以调用相同的方法,那这些类型就共享这种相同的行为.而trait定义就是将这种方法签名组合起来的方法,而它的目的就是定义一个行为集合,这些行为可以实现我们的某个目的
我们来看一个例子:有两个结构体NewsArticle 和 Tweet ,前者存放新闻故事,后者存放元数据,类似转推或回复。但我们现在想要创建一个多媒体聚合库,它显示的是NewsArticle 或 Tweet中的数据总结。每个结构体都对应一个行为(方法),这样,我们就可以定义一个 trait
pub trait Summary {
fn summarize(&self)->String;
}
关于定义trait的语法格式,非常简单。使用关键字trait + trait名称,然后花括号中写具体实现的方法,可以写一个也可以写多个,并且每个都以分号结尾
为类型实现trait
我们把上面的案例再来剖析下,然后在这个两个struct上实现trait,使用impl + trait名称 + for + 具体类型名称 语法格式
pub struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String,
}
impl Summary for NewsArticle {
fn summarize(&self)->String{
format!("{},by {} ({})",self.headline,self.location,self.author)
}
}
pub struct Tweet {
pub username:String,
pub conten