免費(fèi)做外貿(mào)的網(wǎng)站免費(fèi)推廣的平臺
Rust的運(yùn)行時多態(tài)
Rust的靜態(tài)多態(tài)即編譯時多態(tài),通過**泛型+特征約束(Generic Type + Trait Constrait)**來實(shí)現(xiàn);
那么動態(tài)多態(tài)(運(yùn)行時多態(tài))呢?答案是特征對象(Trait Object)。
特征對象不是一個實(shí)例,而是一個結(jié)構(gòu)體類型。
語法是dyn TraitName
,編譯時指示某個對象是實(shí)現(xiàn)TraitName的類型,其具體類型未知。
分析
程序運(yùn)行時,要調(diào)用一個特征方法,需要兩個要素:
- 對象實(shí)例(對象類型未知,因此其編譯期大小未知)
- 特征的方法表
所以特征對象結(jié)構(gòu)體必須獲知以上兩個要素。
發(fā)生運(yùn)行時多態(tài)時,在編譯階段編譯器無法辨別對象實(shí)例的類型,因此對象實(shí)例要素的大小無法獲知,進(jìn)而特征對象(Trait Object)的大小在編譯階段無法被確定,這決定了Trait Object只能存放在堆上,通過引用或智能指針來訪問。
指向特征對象的引用或智能指針,包含了兩個指針成員,在程序運(yùn)行時,ptr1在指向?qū)ο髮?shí)例,ptr2指向該對象類型的Trait Method實(shí)現(xiàn)。
典型用例
#[derive(Debug)]
struct Journal {author: String,year: u16,from: String,
}
#[derive(Debug)]
struct Conference {author: String,year: u16,country: String,
}trait Summary {fn summary(&self) -> String;
}impl std::fmt::Debug for dyn Summary {fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {write!(f, "{}", self.summary())}
}impl Summary for Journal {fn summary(&self) -> String {format!("{}\t{}\t{}", self.author, self.year, self.from)}
}
impl Summary for Conference {fn summary(&self) -> String {format!("{}\t{}\t{}", self.author, self.year, self.country)}
}// can't defer concrete type in compile stage, trait constrain can't used here
// fn init_default(_type: &str) -> impl Summary {
// if _type == "journal" {
// Journal {
// author: "hjd".to_owned(),
// year: 2018,
// from: "Nature".to_owned(),
// }
// } else {
// Conference {
// author: "hjd".to_owned(),
// year: 2018,
// country: "China".to_owned(),
// }
// }
// }// 只能使用特征對象進(jìn)行動態(tài)分發(fā),因?yàn)榉祷仡愋途幾g期無法推理獲知
fn init_default(_type: &str) -> Box<dyn Summary> {if _type == "journal" {Box::new(Journal {author: "hjd".to_owned(),year: 2018,from: "Nature".to_owned(),})} else {Box::new(Conference {author: "hjd".to_owned(),year: 2018,country: "China".to_owned(),})}
}fn main() {let p1 = init_default("journal");let p2 = init_default("conference");let p3 = init_default("journal");let p4 = init_default("conference");let p_list = vec![p1, p2, p3, p4];// dyn Summary是一個特征對象類型,它忘記了自己之前的具體類型,只能調(diào)用Summary特征中的方法for p in p_list.iter() {println!("{:?}", p);}
}