泛型單態化沒有運行時開銷
1、泛型數據結構
枚舉泛型
enum Option<T> {
Some(T),
None,
}
結構體泛型
泛型結構體定義
struct Point<T>{
x:T,
y:T,
} //字段 x 和 y 都是 相同類型的
struct PointTU<T, U>{
x:T,
y:U,
} //字段 x 和 y 可以有不同類型
fn main() {
let int = Point{x:4, y:4};
let fl = Point{x:4.4, y:5.4};
println!("{}, {}", int.x, fl.y);
let hun = PointTU{x:"44", y:4.5};
println!("{}, {}", hun.x, hun.y);
}
泛型結構體方法
struct Point<T>{
x:T,
y:T,
} //字段 x 和 y 都是 相同類型的
impl <T> Point<T>{
fn get_x(&self)->&T{
return &self.x;
}
}
impl Point<f32>{
//計算點實例與座標 (0.0, 0.0) 之間的距離,並使用了只能用於浮點型的數學運算符。
fn distiance_from_origin(&self)->f32{
return (self.x.powi(2) + self.y.powi(2)).sqrt();
}
}
fn main() {
let int:Point<i32> = Point{x:4, y:4};
let fl:Point<f32> = Point{x:2.0, y:2.0};
println!("{}, {}, {}, {}", int.x, fl.y, int.get_x(), fl.distiance_from_origin());
}
實例2:
struct Point<T, U>{
x:T,
y:U,
}
impl <T, U> Point<T, U>{
fn mixup<V, W>(self, other:Point<V, W>)->Point<T, W>{
Point{
x:self.x,
y:other.y,
}
}
}
fn main() {
let p1 = Point{x:5, y:10.4};
let p2 = Point{x:"hello", y:'C'};
let p3 = p2.mixup(p1);
println!("{:?}, {}", p3.x, p3.y)
}
2、trait
什麼是trait
trait用來實現多態。類似C++中的接口
pub trait Summary{
fn summarize(&self)->String;
}
pub struct NewsArticle{
pub headline:String,
pub location:String,
pub author:String,
pub content:String,
}
pub struct Tweet{
pub username:String,
pub content:String,
pub reply:bool,
pub retweet:bool,
}
impl Summary for NewsArticle{
fn summarize(&self)->String{
format!("{}, by {} ({})", self.headline, self.author, self.location)
}
}
impl Summary for Tweet {
fn summarize(&self) -> String {
return format!("{}: {}", self.username, self.content);
}
}
fn main() {
let tweet = Tweet{
username:String::from("horse_ebooks"),
content:String::from("I have nothing"),
reply:false,
retweet:false,
};
println!("{}", tweet.summarize());
let article = NewsArticle {
headline: String::from("NewsArticle_headline"),
location: String::from("Pittsburgh, PA, USA"),
author: String::from("Iceburgh"),
content: String::from("The Pittsburgh Penguins once again are the best hockey team in the NHL."),
};
println!("{}", article.summarize());
}
默認trait
默認指定行爲
pub trait Summary{
fn summarize(&self)->String{
return String::from("默認實現");
}
}
pub struct NewsArticle{
pub headline:String,
pub location:String,
pub author:String,
pub content:String,
}
pub struct Tweet{
pub username:String,
pub content:String,
pub reply:bool,
pub retweet:bool,
}
impl Summary for NewsArticle{ //必須寫
//因爲沒有實現summarize所以會調用默認實現的trait
}
impl Summary for Tweet {
fn summarize(&self) -> String {
return format!("{}: {}", self.username, self.content);
}
}
fn main() {
let tweet = Tweet{
username:String::from("horse_ebooks"),
content:String::from("I have nothing"),
reply:false,
retweet:false,
};
let article = NewsArticle {
headline: String::from("NewsArticle_headline"),
location: String::from("Pittsburgh, PA, USA"),
author: String::from("Iceburgh"),
content: String::from("The Pittsburgh Penguins once again are the best hockey team in the NHL."),
};
println!("{}", tweet.summarize());
println!("{}", article.summarize());
}
trait作爲參數
pub trait Summary{
fn ari_authon(&self)->String;
fn summarize(&self)->String{
return String::from("默認實現");
}
}
pub struct NewsArticle{
pub headline:String,
pub location:String,
pub author:String,
pub content:String,
}
pub struct Tweet{
pub username:String,
pub content:String,
pub reply:bool,
pub retweet:bool,
}
impl Summary for NewsArticle{ //must
fn ari_authon(&self)->String{
return format!("{}", self.author);
}
}
pub fn notify_bound<T:Summary>(item:T){
println!("參數:{}", item.ari_authon())
}
fn main() {
let article = NewsArticle {
headline: String::from("NewsArticle_headline"),
location: String::from("Pittsburgh, PA, USA"),
author: String::from("Iceburgh"),
content: String::from("The Pittsburgh Penguins once again are the best hockey team in the NHL."),
};
println!("{}, {}", article.summarize(), article.ari_authon());
notify_bound(article)
}
trait bound語法糖
pub trait Summary{
fn ari_authon(&self)->String;
fn summarize(&self)->String{
return String::from("默認實現");
}
}
pub struct NewsArticle{
pub headline:String,
pub location:String,
pub author:String,
pub content:String,
}
pub struct Tweet{
pub username:String,
pub content:String,
pub reply:bool,
pub retweet:bool,
}
impl Summary for NewsArticle{ //must
fn ari_authon(&self)->String{
return format!("{}", self.author);
}
}
pub fn notify(item:impl Summary){ //在 notify 函數體中,可以調用任何來自 Summary trait 的方法
println!("參數:{}", item.summarize())
}
fn main() {
let article = NewsArticle {
headline: String::from("NewsArticle_headline"),
location: String::from("Pittsburgh, PA, USA"),
author: String::from("Iceburgh"),
content: String::from("The Pittsburgh Penguins once again are the best hockey team in the NHL."),
};
println!("{}, {}", article.summarize(), article.ari_authon());
notify(article); //值的所有權
}
適用
pub fn notify(item1: impl Summary, item2: impl Summary)
pub fn notify<T: Summary>(item1: T, item2: T)
trait bound實現PartialOrd trait和 Copy trait:
//爲了只對實現了 Copy 的類型調用這些代碼,可以在 T 的 trait bounds 中增加 Copy:error[E0508]: cannot move out of type `[T]`, a non-copy slice
fn largest<T:PartialOrd + Copy>(list:&[T])->T{ //PartialOrd trait (允許比較),or:error[E0369]: binary operation `>` cannot be applied to type `T`
let mut largest = list[0]; //i32 和 char 這樣的類型是已知大小的並可以儲存在棧上,所以他們實現了 Copy trait
//largest 函數改成使用泛型後,現在 list 參數的類型就有可能是沒有實現 Copy trait 的。
//可能不能將 list[0] 的值移動到 largest 變量中
//只要傳遞給 largest 的 slice 值的類型實現了 PartialOrd 和 Copy 這兩個 trait
for &item in list.iter(){
if item > largest{
largest = item;
}
}
largest
}
fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest(&number_list);
println!("{}", result);
let char_list = vec!['y', 'm', 'a', 'q'];
let result = largest(&char_list);
println!("The largest char is {}", result);
}
trait作爲返回值
pub trait Summary{
fn ari_authon(&self)->String;
fn summarize(&self)->String{
return String::from("默認實現");
}
}
pub struct NewsArticle{
pub headline:String,
pub location:String,
pub author:String,
pub content:String,
}
impl Summary for NewsArticle{ //must
fn ari_authon(&self)->String{
return format!("{}", self.author);
}
}
fn returns_summarizable() -> impl Summary {
NewsArticle {
headline: String::from("NewsArticle_headline"),
location: String::from("Pittsburgh, PA, USA"),
author: String::from("Iceburgh"),
content: String::from("The Pittsburgh Penguins once again are the best hockey team in the NHL."),
}
}
fn main() {
let al = returns_summarizable();
println!("{}, {}", al.summarize(), al.ari_authon());
}
只適用於返回單一類型的情況。例如,這樣就 不行:
fn returns_summarizable(switch: bool) -> impl Summary {
if switch {
NewsArticle {
headline: String::from("Penguins win the Stanley Cup Championship!"),
location: String::from("Pittsburgh, PA, USA"),
author: String::from("Iceburgh"),
content: String::from("The Pittsburgh Penguins once again are the best
hockey team in the NHL."),
}
} else {
Tweet {
username: String::from("horse_ebooks"),
content: String::from("of course, as you probably already know, people"),
reply: false,
retweet: false,
}
}
}
參考:https://kaisery.github.io/trpl-zh-cn/ch09-01-unrecoverable-errors-with-panic.html