泛型
泛型是一種參數(shù)化多態(tài),使用泛型可以編寫更為抽象的代碼,減少工作量,簡單來說,泛型就是把一個泛化的類型作為參數(shù),單個類型可以抽象化為一簇類型。
rust在編譯時期會把泛型枚舉,函數(shù),結(jié)構(gòu)體單態(tài)化。
單態(tài)化意味著編譯器要將一個泛型函數(shù)生成多個具體類型對應(yīng)的函數(shù)。
單態(tài)化是編譯器進(jìn)行靜態(tài)分發(fā)的一種策略。
單態(tài)化靜態(tài)分發(fā)的好處是性能好,沒有運行時開銷,缺點是容易造成編譯后生成的二進(jìn)制文件膨脹。
trait是在行為上對類型的約束。
使用場景
接口抽象,接口是對類型行為的統(tǒng)一約束
泛型約束,泛型的行為被trait限定在更有限的范圍內(nèi)
抽象類型,在運行時作為一種間接的抽象類型去使用,動態(tài)的分發(fā)給具體的類型
標(biāo)簽trait,對類型的約束,可以直接作為一種“標(biāo)簽”使用。
接口抽象
trait最基本的用法就是進(jìn)行接口抽象,它有如下特點:
- 接口中可以第一方法,并支持默認(rèn)實現(xiàn)
- 接口中不能實現(xiàn)另一個接口,但是接口之間可以繼承
- 同一個接口可以同時被多個類型實現(xiàn),但不能被同一個類型實現(xiàn)多次
- 使用impl關(guān)鍵字為類型實現(xiàn)接口方法
- 使用trait關(guān)鍵字來定義接口
trait關(guān)聯(lián)類型
使用關(guān)聯(lián)類型能夠是代碼變得更加精簡,同時也對方法的輸入和輸出進(jìn)行來更好的隔離,使得代碼的可讀性大大增強(qiáng)。在語義層面上,使用關(guān)聯(lián)類型也增強(qiáng)來trait表示行為的這種語義,因為它表示來和某個行為(trait)相關(guān)聯(lián)的類型,在工程上也提現(xiàn)了高內(nèi)聚的特點。
孤兒規(guī)則
孤兒規(guī)則規(guī)定,如果實現(xiàn)某個trait,那么該trait和要實現(xiàn)該trait的那個類型至少有一個要在當(dāng)前create中定義。
trait繼承
子trait可以繼承父trait中定義或?qū)崿F(xiàn)的方法。
trait后面的冒號代表trait繼承,其后跟隨要繼承的父trait名稱,如果是多個trait則用加號相連;
泛型約束
trait限定
使用trait對泛型進(jìn)行約束叫trait限定。
在泛型中使用trait限定可以將任意類型的范圍根據(jù)類型的行為限定到更加精確可控的范圍內(nèi)。
trait可以使用where關(guān)鍵字對較多的限定的代碼進(jìn)行重構(gòu)。
在作為泛型限定時,Rust中冒號代表集合的“包含于”關(guān)系,而加號代表這種限定行為交集。
trait限定給予了開發(fā)者更大的自由度,因為不再需要類型間的繼承,也簡化了編譯器的檢查操作,包含trait限定的泛型屬于靜態(tài)分發(fā),在編譯期通過單態(tài)化分別生成具體類型的實例,所以調(diào)用trait限定中的方法也都是運行是零成本的,因為不需要在運行時進(jìn)行方法查找。
抽象類型
抽象類型屬于類型系統(tǒng)的一種,也叫存在類型,相對于具體類型而言,抽象類型無法直接實例化,它的每個實例都是具體類型的實例。
對于抽象類型而言,編譯器可能無法確定其確切的功能和所占的空間大小,所以rust目前有兩種方法來處理抽象類型,trait對象和impl trait
trait對象
trait對象是對具有相同行為的一組具體類型的抽象,將共同擁有相同行為的類型集合抽象為一個類型。
traitObject包含兩個指針:data指針和vtable指針
impl trait
impl Trait只可以在輸入的參數(shù)和返回值這兩個位置使用。
impl trait用在參數(shù)位置時等價于使用trait限定的泛型。impl trait用在返回值位置的時候等價于給返回值類型增加一種trait限定范圍。
標(biāo)簽trait
rust一共提供了5個重要的標(biāo)簽trait,都被定義在標(biāo)準(zhǔn)庫std::marker模塊中
- Sized trait,用來標(biāo)示編譯期可確定大小的類型
- Unsize trait,目前該trait為實驗特性,用于標(biāo)示動態(tài)大小類型
- Copy trait,用來標(biāo)示可以安全地按位復(fù)制其值的類型。
- Send trait,用來標(biāo)示可以跨線程安全通信的類型
- Sync trait,用來標(biāo)示可以在線程間安全共享引用的類型。
Copy trait
copy 是一個標(biāo)簽trait,編譯器做類型檢查時會檢測類型所帶來的標(biāo)簽,以驗證它是否“合格”,copy的行為是一個隱式行為,開發(fā)者不能重載copy行為,它永遠(yuǎn)都是一個簡單的位復(fù)制。
并非所有類型都可以實現(xiàn)copy trait ,對于自定義類型來說,必須讓所有的成員都實現(xiàn)了copy trait這個類型才有資格實現(xiàn)copy trait。
clone trait是一個顯式行為,任何類型都可以實現(xiàn)clone trait
Send trait 和Sync trait
rust提供了語言級的并發(fā)支持,rust憑借Send、Sync和所有權(quán)機(jī)制,在編譯時期就檢查出線程安全問題,保證了無數(shù)據(jù)競爭的的并發(fā)安全問題,讓開發(fā)者可以“無恐慌”地編寫多線程并發(fā)代碼。
rust提供了Send和Sync兩個標(biāo)簽trait,它們是rust無數(shù)據(jù)競爭開發(fā)的基石。
實現(xiàn)send的類型,可以安全地在線程間傳遞值,也就是說可以跨線程傳遞所有權(quán)。
實現(xiàn)了sync的類型,可以跨線程安全地傳遞共享(不可變)引用。
send 和sync標(biāo)簽trait和前面所說的copy,sized一樣,內(nèi)部也沒有具體的方法實現(xiàn),它們僅僅是標(biāo)記可以安全的跨線程傳遞和訪問的類型用send和sync標(biāo)記,否則使用!send 和!sync標(biāo)記