第13ç« å®ç¨ç¹æ§
# 第13ç« å®ç¨ç¹æ§
ç§å¦åªä¸è¿æ¯å¨å¤§èªç¶çååä¸åä¸ââæè æ´ç¡®åå°è¯´ï¼å¨æä»¬ååä¸åçç»éªä¸ââ寻æ¾ç»ä¸æ§çæ¢ç´¢ãç¨æ¯å徿²»ï¼Coleridgeï¼çè¯è¯´ï¼è¯æãç»ç»åèºæ¯ä¹æ¯åæ ·çæ¢ç´¢ï¼å³å¨ååä¸å¯»æ±ç»ä¸ã ââé åå¸Â·å¸ç½è¯ºå¤«æ¯åºï¼Jacob Bronowskiï¼
æ¬ç« å°ä»ç»æä»¬æè¯´çRust âå®ç¨â ç¹æ§ï¼è¿äºç¹æ§æ¥èªæ ååºï¼ç§ç±»ç¹å¤ï¼å®ä»¬å¯¹Rustçç¼ç¨æ¹å¼æçéè¦å½±åã为äºç¼å符åä¹ æ¯ç¨æ³ç代ç ï¼ä»¥åä¸ºä½ çåºè®¾è®¡åºç¨æ·è®¤ä¸º âå¾Rustâ çå ¬å ±æ¥å£ï¼ä½ éè¦çæè¿äºç¹æ§ãå®ä»¬å¤§è´å¯å为ä¸ç±»ï¼
- è¯è¨æ©å±ç¹æ§ï¼æ£å¦æä»¬å¨ä¸ä¸ç« ä»ç»çè¿ç®ç¬¦éè½½ç¹æ§ï¼è®©ä½ è½å¤å¨èªå·±å®ä¹çç±»åä¸ä½¿ç¨Rustç表达å¼è¿ç®ç¬¦ä¸æ ·ï¼æ ååºä¸è¿æå
¶ä»ä¸äºç¹æ§ï¼ä½ä¸ºRustçæ©å±ç¹ï¼è½è®©ä½ å°èªå·±çç±»åä¸è¯è¨æ´ç´§å¯å°éæãè¿äºç¹æ§å
æ¬
DropãDerefåDerefMutï¼ä»¥å转æ¢ç¹æ§FromåIntoãæä»¬å°å¨æ¬ç« ä»ç»è¿äºç¹æ§ã - æ è®°ç¹æ§ï¼è¿äºç¹æ§ä¸»è¦ç¨äºçº¦ææ³åç±»ååéï¼ä»¥è¡¨è¾¾å
¶ä»æ¹å¼æ æ³è¡¨è¾¾ç约æãå
æ¬
SizedåCopyã - å
Œ
±è¯æ±ç¹æ§ï¼è¿äºç¹æ§æ²¡æä»»ä½ç¥å¥çç¼è¯å¨éæåè½ï¼ä½ ä¹å¯ä»¥å¨èªå·±ç代ç ä¸å®ä¹çæçç¹æ§ãä½å®ä»¬æä¸ä¸ªéè¦ä½ç¨ï¼å°±æ¯ä¸ºå¸¸è§é®é¢æä¾äºçº¦å®ä¿æçè§£å³æ¹æ¡ãè¿äºç¹æ§å¨åºä¸æ¨¡åä¹é´çå
Œ
±æ¥å£ä¸ç¹å«æä»·å¼ï¼éè¿åå°ä¸å¿
è¦çå·®å¼ï¼å®ä»¬ä½¿æ¥å£æ´æäºçè§£ï¼åæ¶ä¹å¢å äºä¸ååºçåè½å¯ä»¥ç´æ¥ç»å使ç¨çå¯è½æ§ï¼èæ éç¼åæ ·æ¿ä»£ç æèªå®ä¹ç²å代ç ãè¿äºç¹æ§å
æ¬
Defaultãå¼ç¨åç¨ç¹æ§AsRefãAsMutãBorrowåBorrowMutï¼å¯è½å¤±è´¥ç转æ¢ç¹æ§TryFromåTryIntoï¼ä»¥åToOwnedç¹æ§ï¼å®æ¯Cloneçæ³åã
è¿äºç¹æ§æ»ç»å¨è¡¨13-1ä¸ã 表13-1 å®ç¨ç¹æ§æ»ç»
| ç¹æ§ | æè¿° |
|---|---|
Drop | ææå½æ°ãRustå¨å¼è¢«ä¸¢å¼æ¶èªå¨è¿è¡çæ¸ ç代ç ã |
Sized | æ è®°ç¹æ§ï¼ç¨äºå¨ç¼è¯æ¶å·²ç¥å¤§å°åºå®çç±»åï¼ä¸å¨æå¤§å°çç±»åï¼å¦åçï¼ç¸å¯¹ã |
Clone | æ¯æå éå¼çç±»åã |
Copy | æ è®°ç¹æ§ï¼ç¨äºå¯ä»¥éè¿å¯¹å å«å¼çå åè¿è¡éåèå¤å¶æ¥å®ç°å éçç±»åã |
DerefåDerefMut | æºè½æéç±»åçç¹æ§ã |
Default | å ·æåç âé»è®¤å¼â çç±»åã |
AsRefåAsMut | ä»ä¸ç§ç±»ååç¨å¦ä¸ç§ç±»åå¼ç¨ç转æ¢ç¹æ§ã |
BorrowåBorrowMut | ä¸AsRef/AsMut类似ç转æ¢ç¹æ§ï¼ä½é¢å¤ä¿è¯ä¸è´çåå¸ãæåºåç¸çæ§ã |
FromåInto | å°ä¸ç§ç±»åçå¼è½¬æ¢ä¸ºå¦ä¸ç§ç±»åç转æ¢ç¹æ§ã |
TryFromåTryInto | ç¨äºå¯è½å¤±è´¥çç±»å转æ¢ç转æ¢ç¹æ§ã |
ToOwned | å°å¼ç¨è½¬æ¢ä¸ºæ¥ææææçå¼ç转æ¢ç¹æ§ã |
æ ååºä¸è¿æå
¶ä»éè¦çç¹æ§ãæä»¬å°å¨ç¬¬15ç« ä»ç»IteratoråIntoIteratorã第16ç« ä¼ä»ç»ç¨äºè®¡ç®åå¸ç çHashç¹æ§ã第19ç« å°ä»ç»æ 记线ç¨å®å
¨ç±»åçä¸å¯¹ç¹æ§SendåSyncã
# Drop
å½ä¸ä¸ªå¼çææè æ¶å¤±æ¶ï¼æä»¬è¯´Rust丢å¼äºè¿ä¸ªå¼ã丢å¼ä¸ä¸ªå¼æå³çéæ¾è¯¥å¼ææ¥æçå ¶ä»ä»»ä½å¼ãå åå¨åç³»ç»èµæºã丢å¼å¼çæ 嵿å¾å¤ï¼åéè¶ åºä½ç¨åæ¶ï¼å¨è¡¨è¾¾å¼è¯å¥ç»ææ¶ï¼å½ä½ æªæåéï¼ä»å ¶æ«å°¾ç§»é¤å ç´ æ¶ççã
å¨å¤§å¤æ°æ åµä¸ï¼Rustä¼èªå¨ä¸ºä½ å¤çå¼ç丢å¼ãä¾å¦ï¼åè®¾ä½ å®ä¹äºä»¥ä¸ç±»åï¼
struct Appellation {
name: String,
nicknames: Vec<String>
}
2
3
4
ä¸ä¸ªAppellationæ¥æç¨äºåå¨å符串å
容çå 空é´ååéå
ç´ çç¼å²åºãæ¯å½ä¸ä¸ªAppellationè¢«ä¸¢å¼æ¶ï¼Rustä¼è´è´£æ¸
çææè¿äºèµæºï¼ä½ æ éåç¼åé¢å¤ç代ç ãä¸è¿ï¼å¦æä½ æ¿æï¼å¯ä»¥éè¿å®ç°std::ops::Dropç¹æ§æ¥èªå®ä¹Rust丢å¼ä½ å®ä¹ç±»åçå¼çæ¹å¼ï¼
trait Drop {
fn drop(&mut self);
}
2
3
Dropçå®ç°ç±»ä¼¼äºC++ä¸çææå½æ°ï¼æè
å
¶ä»è¯è¨ä¸çç»ç»å¨ãå½ä¸ä¸ªå¼è¢«ä¸¢å¼æ¶ï¼å¦æå®å®ç°äºstd::ops::Dropï¼Rustä¼å¨åå¾å¸¸ä¸æ ·ç»§ç»ä¸¢å¼å
¶å段æå
ç´ ææ¥æçå¼ä¹åï¼è°ç¨å
¶dropæ¹æ³ãè¿ç§å¯¹dropçéå¼è°ç¨æ¯è°ç¨è¯¥æ¹æ³çå¯ä¸æ¹å¼ï¼å¦æä½ è¯å¾æ¾å¼è°ç¨å®ï¼Rustä¼å°å
¶æ 记为é误ã
å 为Rustå¨ä¸¢å¼ä¸ä¸ªå¼çåæ®µæå
ç´ ä¹åä¼è°ç¨Drop::dropï¼æä»¥è¯¥æ¹æ³æ¥æ¶å°çå¼å§ç»æ¯å®å
¨åå§åçãæä»¬ä¸ºAppellationç±»åå®ç°çDropå¯ä»¥å
åå©ç¨å
¶å段ï¼
impl Drop for Appellation {
fn drop(&mut self) {
print!("Dropping {}", self.name);
if !self.nicknames.is_empty() {
print!(" (AKA {})", self.nicknames.join(", "));
}
println!("");
}
}
2
3
4
5
6
7
8
9
æäºè¿ä¸ªå®ç°ï¼æä»¬å¯ä»¥ç¼å以ä¸ä»£ç ï¼
{
let mut a = Appellation {
name: "Zeus".to_string(),
nicknames: vec!["cloud collector".to_string(), "king of the gods".to_string()]
};
println!("before assignment");
a = Appellation { name: "Hera".to_string(), nicknames: vec![] };
println!("at end of block");
}
2
3
4
5
6
7
8
9
彿们å°ç¬¬äºä¸ªAppellationèµå¼ç»aæ¶ï¼ç¬¬ä¸ä¸ªä¼è¢«ä¸¢å¼ï¼å½aè¶
åºä½ç¨åæ¶ï¼ç¬¬äºä¸ªä¹ä¼è¢«ä¸¢å¼ãè¿æ®µä»£ç çè¾åºå¦ä¸ï¼
before assignment
Dropping Zeus (AKA cloud collector, king of the gods)
at end of block
Dropping Hera
2
3
4
ç±äºæä»¬ä¸ºAppellationå®ç°çstd::ops::Dropåªæ¯æå°ä¸æ¡æ¶æ¯ï¼é£ä¹å®çå
åå°åºæ¯å¦ä½æ¸
ççå¢ï¼Vecç±»åå®ç°äºDropï¼å®ä¼ä¸¢å¼æ¯ä¸ªå
ç´ ï¼ç¶åéæ¾å®ä»¬å ç¨çå åé
ç¼å²åºãStringå
é¨ä½¿ç¨Vec<u8>æ¥å卿æ¬ï¼æä»¥Stringæ¬èº«æ éå®ç°Dropï¼å®è®©å
¶å
é¨çVecæ¥è´è´£éæ¾å符ãåæ ·çåçä¹éç¨äºAppellationå¼ï¼å½ä¸ä¸ªAppellationå¼è¢«ä¸¢å¼æ¶ï¼æç»æ¯VecçDropå®ç°è´è´£éæ¾æ¯ä¸ªå符串çå
å®¹ï¼æåéæ¾åå¨åéå
ç´ çç¼å²åºãè³äºåå¨Appellation弿¬èº«çå
åï¼å®ä¹ææä¸ªææè
ï¼å¯è½æ¯ä¸ä¸ªå±é¨åéææä¸ªæ°æ®ç»æï¼ç±è¿ä¸ªææè
è´è´£éæ¾å®ã
妿ä¸ä¸ªåéçå¼è¢«ç§»å¨å°å ¶ä»å°æ¹ï¼å¯¼è´è¯¥åéå¨è¶ åºä½ç¨åæ¶æªåå§åï¼é£ä¹Rustä¸ä¼å°è¯ä¸¢å¼è¯¥åéï¼å ä¸ºå ¶ä¸æ²¡æå¼å¯ä¸¢å¼ã
å³ä½¿ä¸ä¸ªåéç弿¯å¦è¢«ç§»å¨åå³äºæ§å¶æµï¼è¿æ¡ååä»ç¶éç¨ãå¨è¿ç§æ åµä¸ï¼Rustä¼ç¨ä¸ä¸ªä¸å¯è§çæ å¿æ¥è·è¸ªåéçç¶æï¼æç¤ºè¯¥åéç弿¯å¦éè¦è¢«ä¸¢å¼ï¼
let p;
{
let q = Appellation { name: "Cardamine hirsuta".to_string(),
nicknames: vec!["shotweed".to_string(), "bittercress".to_string()] };
if complicated_condition() {
p = q;
}
}
println!("Sproing! What was that?");
2
3
4
5
6
7
8
9
æ ¹æ®complicated_conditionè¿åtrueè¿æ¯falseï¼pæqæç»ä¼æ¥æAppellationï¼èå¦ä¸ä¸ªåæªåå§åãAppellationå¼çæç»å½å±å³å®äºå®æ¯å¨println!ä¹åè¿æ¯ä¹å被丢å¼ï¼å 为qå¨println!ä¹åè¶
åºä½ç¨åï¼èpå¨ä¹åãè½ç¶ä¸ä¸ªå¼å¯è½ä¼å¨ä¸åå°æ¹ç§»å¨ï¼ä½Ruståªä¼ä¸¢å¼å®ä¸æ¬¡ã
é常ï¼é¤éä½ å®ä¹çç±»åæ¥æRustå°æªç¥æçèµæºï¼å¦åä¸éè¦å®ç°std::ops::Dropãä¾å¦ï¼å¨Unixç³»ç»ä¸ï¼Rustæ ååºå
é¨ä½¿ç¨ä»¥ä¸ç±»åæ¥è¡¨ç¤ºæä½ç³»ç»æä»¶æè¿°ç¬¦ï¼
struct FileDesc {
fd: c_int,
}
2
3
FileDescçfdåæ®µåªæ¯ç¨åºä½¿ç¨å®ååºè¯¥å
³éçæä»¶æè¿°ç¬¦ç¼å·ï¼c_intæ¯i32çå«åãæ ååºä¸ºFileDescå®ç°Dropå¦ä¸ï¼
impl Drop for FileDesc {
fn drop(&mut self) {
let _ = unsafe { libc::close(self.fd) };
}
}
2
3
4
5
è¿éï¼libc::closeæ¯Rust对Cåºclose彿°çç§°å¼ãRust代ç åªè½å¨unsafeåä¸è°ç¨C彿°ï¼æä»¥è¿é使ç¨äºunsafeåã
妿ä¸ä¸ªç±»åå®ç°äºDropï¼å®å°±ä¸è½åå®ç°Copyç¹æ§ã妿ä¸ä¸ªç±»åæ¯Copyï¼è¿æå³çç®åçéåèå¤å¶å°±è¶³ä»¥çæè¯¥å¼çç¬ç«å¯æ¬ãä½é常æ
åµä¸ï¼å¯¹å䏿°æ®å¤æ¬¡è°ç¨ç¸åçdropæ¹æ³æ¯é误çã
æ åå置模åä¸å
å«ä¸ä¸ªç¨äºä¸¢å¼å¼ç彿°dropï¼ä½å®çå®ä¹å¹¶æ²¡æä»ä¹ç¥å¥ä¹å¤ï¼
fn drop<T>(_x: T) {}
æ¢å¥è¯è¯´ï¼å®æå¼æ¥æ¶åæ°ï¼ä»è°ç¨è
é£éè·åæææï¼ç¶åä¸å¯¹å
¶è¿è¡ä»»ä½æä½ãå½_xè¶
åºä½ç¨åæ¶ï¼Rustä¼åå¤çå
¶ä»ä»»ä½åé䏿 ·ä¸¢å¼å®çå¼ã
# Sized
大å°ç¡®å®ï¼sizedï¼ç±»åæçæ¯å
¶ææå¼å¨å
åä¸å¤§å°é½ç¸åçç±»åãRustä¸å 乿æç±»å齿¯å¤§å°ç¡®å®çï¼æ¯ä¸ªu64å ç¨8个åèï¼æ¯ä¸ª(f32, f32, f32)å
ç»å ç¨12个åèãçè³æä¸¾ç±»å乿¯å¤§å°ç¡®å®çï¼æ 论å®é
使ç¨åªä¸ªåä½ï¼æä¸¾å§ç»å ç¨è¶³å¤çç©ºé´æ¥å®¹çº³å
¶æå¤§çåä½ãè½ç¶Vec<T>æ¥æä¸ä¸ªå¤§å°å¯åçå åé
ç¼å²åºï¼ä½Vec弿¬èº«æ¯ä¸ä¸ªæåç¼å²åºã容éåé¿åº¦çæéï¼æä»¥Vec<T>æ¯ä¸ä¸ªå¤§å°ç¡®å®çç±»åã
ææå¤§å°ç¡®å®çç±»åé½å®ç°äºstd::marker::Sizedç¹æ§ï¼è¯¥ç¹æ§æ²¡ææ¹æ³æå
³èç±»åãRustä¼èªå¨ä¸ºææéç¨çç±»åå®ç°å®ï¼ä½ ä¸è½èªå·±å®ç°è¿ä¸ªç¹æ§ãSizedå¯ä¸çç¨éæ¯ä½ä¸ºç±»ååéç约æï¼åT: Sizedè¿æ ·ç约æè¦æ±Tæ¯ä¸ä¸ªå¨ç¼è¯æ¶å·²ç¥å¤§å°çç±»åãè¿ç±»ç¹æ§è¢«ç§°ä¸ºæ è®°ç¹æ§ï¼marker traitsï¼ï¼å 为Rustè¯è¨æ¬èº«ç¨å®ä»¬æ¥æ è®°æäºå
·æç¹å®æè¶£ç¹å¾çç±»åã
ä¸è¿ï¼Rust乿ä¸äºå¤§å°ä¸ç¡®å®ï¼unsizedï¼çç±»åï¼å
¶å¼ç大å°å¹¶ä¸é½ç¸åãä¾å¦ï¼å符串åçç±»åstrï¼æ³¨æï¼è¿é没æ&ï¼æ¯å¤§å°ä¸ç¡®å®çãå符串åé¢é"diminutive"å"big"æ¯æåstråççå¼ç¨ï¼åå«å ç¨10个åèå3个åèãå¦å¾13-1æç¤ºãå[T]ï¼åæ ·æ²¡æ&ï¼è¿æ ·çæ°ç»åçç±»å乿¯å¤§å°ä¸ç¡®å®çï¼å&[u8]è¿æ ·çå
±äº«å¼ç¨å¯ä»¥æåä»»æå¤§å°ç[u8]åçãç±äºstrå[T]ç±»å表示大å°ä¸åçå¼çéåï¼æä»¥å®ä»¬æ¯å¤§å°ä¸ç¡®å®çç±»åã
å¾13-1 æå大å°ä¸ç¡®å®å¼çå¼ç¨
Rustä¸å¦ä¸ç§å¸¸è§ç大å°ä¸ç¡®å®çç±»åæ¯dynç±»åï¼å³ç¹æ§å¯¹è±¡çå¼ç¨ç®æ ãæ£å¦æä»¬å¨ âç¹æ§å¯¹è±¡â ä¸è§£éçï¼ç¹æ§å¯¹è±¡æ¯æåæä¸ªå®ç°äºç»å®ç¹æ§çå¼çæéãä¾å¦ï¼&dyn std::io::WriteåBox<dyn std::io::Write>ç±»åæ¯æåæä¸ªå®ç°äºWriteç¹æ§çå¼çæéã该å¼ç¨ç®æ å¯è½æ¯ä¸ä¸ªæä»¶ãç½ç»å¥æ¥åï¼æè
æ¯ä½ èªå·±å®ç°äºWriteç¹æ§çæç§ç±»åãç±äºå®ç°Writeç¹æ§çç±»åé忝弿¾çï¼æä»¥dyn Writeä½ä¸ºä¸ç§ç±»åæ¯å¤§å°ä¸ç¡®å®çï¼å®ç弿ä¸åç大å°ã
Rustä¸è½å°å¤§å°ä¸ç¡®å®çå¼åå¨å¨åéä¸ï¼ä¹ä¸è½å°å®ä»¬ä½ä¸ºåæ°ä¼ éãä½ åªè½éè¿å&stræBox<dyn Write>è¿æ ·çæéæ¥å¤çå®ä»¬ï¼èè¿äºæéæ¬èº«æ¯å¤§å°ç¡®å®çãå¦å¾13-1æç¤ºï¼æå大å°ä¸ç¡®å®å¼çæéæ»æ¯ä¸ä¸ªèæéï¼å ç¨ä¸¤ä¸ªæºå¨åé¿ï¼æååççæéè¿ä¼æºå¸¦åççé¿åº¦ï¼ç¹æ§å¯¹è±¡è¿ä¼æºå¸¦ä¸ä¸ªæåæ¹æ³å®ç°è表ï¼vtableï¼çæéã
ç¹æ§å¯¹è±¡åæååççæéæå¾å¥½ç对称æ§ãå¨è¿ä¸¤ç§æ
åµä¸ï¼ç±»åé½ç¼ºå°ä½¿ç¨å®æéçä¿¡æ¯ï¼ä¸ç¥é[u8]çé¿åº¦ï¼ä½ å°±æ æ³å¯¹å
¶è¿è¡ç´¢å¼ï¼ä¸ç¥éBox<dyn Write>ææåçå
·ä½å¼å¯¹åºçWriteå®ç°ï¼ä½ å°±æ æ³è°ç¨å
¶æ¹æ³ãå¨è¿ä¸¤ç§æ
åµä¸ï¼èæéé½è¡¥å
äºç±»åæç¼ºå°çä¿¡æ¯ï¼æºå¸¦äºé¿åº¦æè表æéãçç¥çéæä¿¡æ¯è¢«å¨æä¿¡æ¯æå代ã
ç±äºå¤§å°ä¸ç¡®å®çç±»åæè¯¸å¤éå¶ï¼å¤§å¤æ°æ³åç±»ååéåºè¯¥éå¶ä¸ºå¤§å°ç¡®å®çç±»åãå®é
ä¸ï¼è¿ç§éæ±é常常è§ï¼ä»¥è³äºå¨Rustä¸è¿æ¯éå¼é»è®¤çï¼å¦æä½ åstruct S<T> { ... }ï¼Rustä¼ç解为struct S<T: Sized> { ... }ãå¦æä½ ä¸æ³è¿æ ·çº¦æTï¼å°±å¿
é¡»æ¾å¼åæ¶è¿ç§éå¶ï¼åæstruct S<T: ?Sized> { ... }ã?Sizedè¯æ³ä»
ç¨äºè¿ç§æ
åµï¼æææ¯ âä¸ä¸å®æ¯å¤§å°ç¡®å®çâãä¾å¦ï¼å¦æä½ åstruct S<T: ?Sized> { b: Box<T> }ï¼é£ä¹Rustä¼å
è®¸ä½ ä½¿ç¨S<str>åS<dyn Write>ï¼æ¤æ¶Boxä¼åæèæéï¼åæ¶ä¹å
许使ç¨S<i32>åS<String>ï¼æ¤æ¶Boxæ¯æ®éæéã
尽管æè¿äºéå¶ï¼å¤§å°ä¸ç¡®å®çç±»å使Rustçç±»åç³»ç»å·¥ä½å¾æ´å 顺ç
ãé
读æ ååºææ¡£æ¶ï¼ä½ å¶å°ä¼éå°ç±»ååéä¸ç?Sized约æï¼è¿å 乿»æ¯æå³çç»å®çç±»åä»
éè¿æé使ç¨ï¼å¹¶ä¸å
许ç¸å
³ä»£ç åæ¶å¤çåçãç¹æ§å¯¹è±¡åæ®éå¼ãå½ä¸ä¸ªç±»ååéæ?Sizedçº¦ææ¶ï¼äººä»¬é常说å®ç大尿¯ä¸ç¡®å®çï¼å®å¯è½æ¯å¤§å°ç¡®å®çï¼ä¹å¯è½ä¸æ¯ã
é¤äºåçåç¹æ§å¯¹è±¡ï¼è¿æä¸ç§å¤§å°ä¸ç¡®å®çç±»åãç»æä½ç±»åçæåä¸ä¸ªå段ï¼ä½åªè½æ¯æåä¸ä¸ªå段ï¼å¯ä»¥æ¯å¤§å°ä¸ç¡®å®çï¼è¿æ ·çç»æä½æ¬èº«ä¹æ¯å¤§å°ä¸ç¡®å®çãä¾å¦ï¼Rc<T>å¼ç¨è®¡æ°æéå¨å
é¨è¢«å®ç°ä¸ºæåç§æç±»åRcBox<T>çæéï¼RcBox<T>å°å¼ç¨è®¡æ°ä¸Tåå¨å¨ä¸èµ·ãä¸é¢æ¯RcBoxçç®åå®ä¹ï¼
struct RcBox<T: ?Sized> {
ref_count: usize,
value: T,
}
2
3
4
valueåæ®µæ¯Rc<T>æ£å¨è®¡æ°å¼ç¨çTï¼Rc<T>è§£å¼ç¨åå¾å°çæéæåè¿ä¸ªå段ãref_countåæ®µä¿åå¼ç¨è®¡æ°ã
çæ£çRcBoxåªæ¯æ ååºçå®ç°ç»èï¼ä¸ä¾å
¬å¼ä½¿ç¨ãä½å设æä»¬ä½¿ç¨åé¢çå®ä¹ãä½ å¯ä»¥å°è¿ä¸ªRcBoxä¸å¤§å°ç¡®å®çç±»åä¸èµ·ä½¿ç¨ï¼æ¯å¦RcBox<String>ï¼ç»ææ¯ä¸ä¸ªå¤§å°ç¡®å®çç»æä½ç±»åãä½ ä¹å¯ä»¥å°å®ä¸å¤§å°ä¸ç¡®å®çç±»åä¸èµ·ä½¿ç¨ï¼æ¯å¦RcBox<dyn std::fmt::Display>ï¼å
¶ä¸Displayæ¯ç¨äºå¯ä»¥è¢«println!åç±»ä¼¼å®æ ¼å¼åçç±»åçç¹æ§ï¼ï¼RcBox<dyn Display>æ¯ä¸ä¸ªå¤§å°ä¸ç¡®å®çç»æä½ç±»åã
ä½ ä¸è½ç´æ¥æå»ºä¸ä¸ªRcBox<dyn Display>å¼ãç¸åï¼ä½ é¦å
éè¦å建ä¸ä¸ªæ®éçã大å°ç¡®å®çRcBoxï¼å
¶å¼ç±»åè¦å®ç°Displayï¼æ¯å¦RcBox<String>ãç¶åï¼Rustå
è®¸ä½ å°å¼ç¨&RcBox<String>转æ¢ä¸ºèå¼ç¨&RcBox<dyn Display>ï¼
let boxed_lunch: RcBox<String> = RcBox { ref_count: 1, value: "lunch".to_string() };
use std::fmt::Display;
let boxed_displayable: &RcBox<dyn Display> = &boxed_lunch;
2
3
å¨å°å¼ä¼ éç»å½æ°æ¶ï¼è¿ç§è½¬æ¢ä¼éå¼åçï¼æä»¥ä½ å¯ä»¥å°&RcBox<String>ä¼ éç»ä¸ä¸ªææ&RcBox<dyn Display>ç彿°ï¼
fn display(boxed: &RcBox<dyn Display>) {
println!("For your enjoyment: {}", &boxed.value);
}
display(&boxed_lunch);
2
3
4
è¿å°äº§ç以ä¸è¾åºï¼For your enjoyment: lunch
# Clone
std::clone::Cloneç¹æ§ç¨äºé£äºå¯ä»¥å建èªèº«å¯æ¬çç±»åãCloneå®ä¹å¦ä¸ï¼
trait Clone : Sized {
fn clone(&self) -> Self;
fn clone_from(&mut self, source: &Self) {
*self = source.clone()
}
}
2
3
4
5
6
cloneæ¹æ³åºè¯¥æé ä¸ä¸ªselfçç¬ç«å¯æ¬å¹¶è¿åãç±äºè¿ä¸ªæ¹æ³çè¿åç±»åæ¯Selfï¼å¹¶ä¸å½æ°ä¸è½è¿å大å°ä¸ç¡®å®çå¼ï¼æä»¥Cloneç¹æ§æ¬èº«æ©å±äºSizedç¹æ§ï¼è¿ä½¿å¾å®ç°Cloneç¹æ§çSelfç±»åå¿
é¡»æ¯å¤§å°ç¡®å®çã
å
éä¸ä¸ªå¼é常è¿éè¦åé
å
¶æ¥æçä»»ä½å
容ç坿¬ï¼æä»¥å
é卿¶é´åå
åä¸å¯è½å¼éå¾å¤§ãä¾å¦ï¼å
éä¸ä¸ªVec<String>ä¸ä»
è¦å¤å¶åéï¼è¿è¦å¤å¶å
¶ä¸çæ¯ä¸ªStringå
ç´ ãè¿å°±æ¯ä¸ºä»ä¹Rustä¸ä¼èªå¨å
éå¼ï¼èæ¯è¦æ±ä½ æ¾å¼è°ç¨æ¹æ³ãåRc<T>åArc<T>è¿æ ·çå¼ç¨è®¡æ°æéç±»åæ¯ä¾å¤ï¼å
éå®ä»¬åªæ¯å¢å å¼ç¨è®¡æ°å¹¶è¿åä¸ä¸ªæ°æéã
clone_fromæ¹æ³å°selfä¿®æ¹ä¸ºsourceç坿¬ãclone_fromçé»è®¤å®ä¹åªæ¯å
ésourceï¼ç¶åå°å
¶ç§»å¨å°*selfä¸ãè¿æ»æ¯å¯è¡çï¼ä½å¯¹äºæäºç±»åï¼ææ´å¿«çæ¹æ³å¯ä»¥è¾¾å°ç¸åçææãä¾å¦ï¼å设såtæ¯Stringç±»åãè¯å¥s = t.clone();å¿
é¡»å
étï¼ä¸¢å¼sçæ§å¼ï¼ç¶åå°å
éçå¼ç§»å¨å°sä¸ï¼è¿æ¶å䏿¬¡å åé
å䏿¬¡å éæ¾ã使¯ï¼å¦æåæ¥sçå ç¼å²åºæè¶³å¤çå®¹éæ¥å®¹çº³tçå
容ï¼å°±ä¸éè¦è¿è¡åé
æéæ¾æä½ï¼ä½ å¯ä»¥ç´æ¥å°tçææ¬å¤å¶å°sçç¼å²åºä¸å¹¶è°æ´é¿åº¦ã卿³å代ç ä¸ï¼åªè¦å¯è½ï¼ä½ é½åºè¯¥ä½¿ç¨clone_fromï¼ä»¥ä¾¿å¨æä¼åå®ç°æ¶å©ç¨å®ä»¬ã
å¦æä½ çCloneå®ç°åªæ¯å¯¹ç±»åçæ¯ä¸ªåæ®µæå
ç´ åºç¨cloneï¼ç¶åç¨è¿äºå
é弿é ä¸ä¸ªæ°å¼ï¼å¹¶ä¸clone_fromçé»è®¤å®ä¹å°±è¶³å¤äºï¼é£ä¹Rustä¼ä¸ºä½ å®ç°è¿äºï¼åªéå¨ç±»åå®ä¹ä¸æ¹å ä¸#[derive(Clone)]ã
æ ååºä¸å 乿æéåå¤å¶çç±»åé½å®ç°äºCloneãåboolåi32è¿æ ·çåºæ¬ç±»åå®ç°äºè¯¥ç¹æ§ãåStringãVec<T>åHashMapè¿æ ·ç容å¨ç±»åä¹å®ç°äºãæäºç±»åä¸éåå¤å¶ï¼æ¯å¦std::sync::Mutexï¼è¿äºç±»å没æå®ç°Cloneãæäºç±»åï¼æ¯å¦std::fs::Fileï¼å¯ä»¥å¤å¶ï¼ä½å¦ææä½ç³»ç»æ²¡æå¿
è¦çèµæºï¼å¤å¶å¯è½ä¼å¤±è´¥ï¼è¿äºç±»å没æå®ç°Cloneï¼å 为cloneå¿
é¡»æ¯å¯é çãç¸åï¼std::fs::Fileæä¾äºä¸ä¸ªtry_cloneæ¹æ³ï¼å®è¿åä¸ä¸ªstd::io::Result<File>ï¼å¯ä»¥æ¥åå¤å¶å¤±è´¥çæ
åµã
# Copy
å¨ç¬¬4ç« ä¸ï¼æä»¬è§£éè¿ï¼å¯¹äºå¤§å¤æ°ç±»åèè¨ï¼èµå¼æä½æ¯ç§»å¨å¼ï¼èéå¤å¶å¼ãç§»å¨å¼è½è®©è·è¸ªå®ä»¬ææ¥æçèµæºå徿´ä¸ºç®åãä½å¨ âå¤å¶ç±»åï¼ç§»å¨çä¾å¤æ åµâ ä¸ï¼æä»¬æåºäºä¾å¤æ åµï¼ä¸æ¥æä»»ä½èµæºçç®åç±»åå¯ä»¥æ¯å¤å¶ï¼Copyï¼ç±»åï¼å¨è¿ç±»ç±»åä¸ï¼èµå¼ä¼å¯¹æºå¼è¿è¡å¤å¶ï¼è䏿¯ç§»å¨å¼å¹¶ä½¿æºå¼å¤äºæªåå§åç¶æã
彿¶ï¼æä»¬å¹¶æªæç¡®è¯´æå¤å¶ï¼Copyï¼ç©¶ç«æ¯ä»ä¹ï¼ç°å¨å¯ä»¥åè¯ä½ ï¼å¦æä¸ä¸ªç±»åå®ç°äºstd::marker::Copyæ è®°ç¹æ§ï¼é£ä¹å®å°±æ¯å¤å¶ç±»åï¼è¯¥ç¹æ§å®ä¹å¦ä¸ï¼
trait Copy : Clone { }
ä¸ºä½ èªå·±å®ä¹çç±»åå®ç°è¿ä¸ªç¹æ§ç¡®å®å¾å®¹æï¼
impl Copy for MyType { }
ä½ç±äºCopyæ¯ä¸ä¸ªå¯¹è¯è¨æçç¹æ®æä¹çæ è®°ç¹æ§ï¼Rustä»
å
许å¨åªéè¿è¡æµ
åèéåèå¤å¶çæ
åµä¸ï¼ä¸ä¸ªç±»åæè½å®ç°Copyãæ¥æè¯¸å¦å ç¼å²åºææä½ç³»ç»å¥æçå
¶ä»ä»»ä½èµæºçç±»åï¼é½æ æ³å®ç°Copyã
ä»»ä½å®ç°äºDropç¹æ§çç±»åé½ä¸å¯è½æ¯Copyç±»åãRust认为ï¼å¦æä¸ä¸ªç±»åéè¦ç¹æ®çæ¸
ç代ç ï¼é£å®å¿
ç¶ä¹éè¦ç¹æ®çå¤å¶ä»£ç ï¼å æ¤ä¸è½æä¸ºCopyç±»åã
ä¸Cloneç¹æ§ä¸æ ·ï¼ä½ å¯ä»¥è®©Rustä¸ºä½ æ´¾çCopyç¹æ§ï¼ä½¿ç¨#[derive(Copy)]ãä½ ç»å¸¸ä¼çå°åæ¶æ´¾çè¿ä¸¤ä¸ªç¹æ§ï¼å³#[derive(Copy, Clone)]ã
å¨å°ä¸ä¸ªç±»å设为Copyç±»åä¹åï¼è¯·ä»ç»èèãå°½ç®¡è¿æ ·åä¼è®©ç±»å使ç¨èµ·æ¥æ´æ¹ä¾¿ï¼ä½å®å¯¹ç±»åçå®ç°æçä¸¥æ ¼çéå¶ãéå¼å¤å¶ä¹å¯è½ä¼å¸¦æ¥è¾é«çå¼éãæä»¬å¨ âå¤å¶ç±»åï¼ç§»å¨çä¾å¤æ
åµâ ä¸è¯¦ç»è§£éäºè¿äºå ç´ ã
# Deref å DerefMut
ä½ å¯ä»¥éè¿å®ç°std::ops::Derefåstd::ops::DerefMutç¹æ§ï¼æ¥æå®å*å.è¿æ ·çè§£å¼ç¨è¿ç®ç¬¦å¨ä½ çç±»åä¸çè¡ä¸ºæ¹å¼ã诸å¦Box<T>åRc<T>çæéç±»åå®ç°äºè¿äºç¹æ§ï¼ä»¥ä¾¿å®ä»¬è½åRustçå
ç½®æéç±»å飿 ·å·¥ä½ãä¾å¦ï¼å¦æä½ æä¸ä¸ªBox<Complex>å¼bï¼é£ä¹*bæçæ¯bææåçComplexå¼ï¼b.reæçæ¯å
¶çå®åéã妿ä¸ä¸æå¯¹å¼ç¨ç®æ è¿è¡èµå¼æåç¨å¯åå¼ç¨ï¼Rustä¼ä½¿ç¨DerefMutï¼âå¯åè§£å¼ç¨â ï¼ç¹æ§ï¼å¦åï¼åªè¯»è®¿é®å°±è¶³å¤äºï¼æ¤æ¶ä¼ä½¿ç¨Derefç¹æ§ã
è¿äºç¹æ§çå®ä¹å¦ä¸ï¼
trait Deref {
type Target: ?Sized;
fn deref(&self) -> &Self::Target;
}
trait DerefMut : Deref {
fn deref_mut(&mut self) -> &mut Self::Target;
}
2
3
4
5
6
7
8
derefåderef_mutæ¹æ³æ¥åä¸ä¸ª&Selfå¼ç¨ï¼å¹¶è¿åä¸ä¸ª&Self::Targetå¼ç¨ãTargetåºè¯¥æ¯Selfå
å«ãæ¥ææå¼ç¨çå
容ï¼å¯¹äºBox<Complex>ï¼Targetç±»åæ¯Complexã请注æï¼DerefMutæ©å±äºDerefï¼å¦æä½ è½å¯¹æä¸ªå¼è¿è¡è§£å¼ç¨å¹¶ä¿®æ¹å®ï¼é£ä¹ä½ è¯å®ä¹åºè¯¥è½å¤åç¨å¯¹å®çå
±äº«å¼ç¨ãç±äºè¿äºæ¹æ³è¿åçå¼ç¨ä¸&selfå
·æç¸åççå½å¨æï¼æä»¥åªè¦è¿åçå¼ç¨åå¨ï¼selfå°±ä¼ä¸ç´å¤äºè¢«åç¨ç¶æã
DerefåDerefMutç¹æ§è¿æå¦ä¸ä¸ªä½ç¨ãç±äºderefæ¥åä¸ä¸ª&Selfå¼ç¨å¹¶è¿åä¸ä¸ª&Self::Targetå¼ç¨ï¼Rustå©ç¨è¿ä¸ç¹èªå¨å°åä¸ç§ç±»åçå¼ç¨è½¬æ¢ä¸ºåä¸ç§ç±»åãæ¢å¥è¯è¯´ï¼å¦ææå
¥ä¸ä¸ªè§£å¼ç¨è°ç¨è½å¤é¿å
ç±»åä¸å¹é
ï¼Rustä¼ä¸ºä½ æå
¥ä¸ä¸ªãå®ç°DerefMutå为å¯åå¼ç¨å¯ç¨äºç¸åºç转æ¢ãè¿äºè¢«ç§°ä¸ºè§£å¼ç¨å¼ºå¶è½¬æ¢ï¼deref coercionsï¼ï¼ä¸ç§ç±»å被 â强å¶â 表ç°å¾åå¦ä¸ç§ç±»åã
è½ç¶è§£å¼ç¨å¼ºå¶è½¬æ¢çæä½ä½ èªå·±ä¹å¯ä»¥æ¾å¼å°ååºæ¥ï¼ä½å®ä»¬é常æ¹ä¾¿ï¼
- å¦æä½ ææä¸ª
Rc<String>å¼rï¼å¹¶æ³å¯¹å®åºç¨String::findæ¹æ³ï¼ä½ å¯ä»¥ç´æ¥år.find('?')ï¼è䏿¯(*r).find('?')ï¼æ¹æ³è°ç¨ä¼éå¼åç¨rï¼å¹¶ä¸ç±äºRc<T>å®ç°äºDeref<Target=T>ï¼&Rc<String>ä¼å¼ºå¶è½¬æ¢ä¸º&Stringã - ä½ å¯ä»¥å¯¹
Stringå¼ä½¿ç¨è¯¸å¦split_atè¿æ ·çæ¹æ³ï¼å°½ç®¡split_atæ¯stråçç±»åçæ¹æ³ï¼è¿æ¯å 为Stringå®ç°äºDeref<Target=str>ãStringæ ééæ°å®ç°strçæææ¹æ³ï¼å ä¸ºä½ å¯ä»¥ä»&String强å¶è½¬æ¢å¾å°&strã - å¦æä½ æä¸ä¸ªåèåé
vï¼å¹¶ä¸æ³å°å®ä¼ éç»ä¸ä¸ªææåèåç&[u8]ç彿°ï¼ä½ å¯ä»¥ç´æ¥å°&vä½ä¸ºåæ°ä¼ éï¼å 为Vec<T>å®ç°äºDeref<Target=[T]>ã
妿å¿
è¦ï¼Rustä¼è¿ç»åºç¨å¤ä¸ªè§£å¼ç¨å¼ºå¶è½¬æ¢ãä¾å¦ï¼å©ç¨å颿å°ç强å¶è½¬æ¢ï¼ä½ å¯ä»¥ç´æ¥å¯¹Rc<String>åºç¨split_atæ¹æ³ï¼å 为&Rc<String>è§£å¼ç¨åå¾å°&Stringï¼&Stringåè§£å¼ç¨å¾å°&strï¼è&stræsplit_atæ¹æ³ãä¾å¦ï¼åè®¾ä½ æä»¥ä¸ç±»åï¼
struct Selector<T> {
/// æ¤`Selector`ä¸å¯ç¨çå
ç´ ã
elements: Vec<T>,
/// `elements`ä¸âå½åâå
ç´ çç´¢å¼ã`Selector`çè¡ä¸ºç±»ä¼¼äºæåå½åå
ç´ çæéã
current: usize
}
2
3
4
5
6
为äºè®©Selectorçè¡ä¸ºç¬¦åææ¡£æ³¨éä¸çæè¿°ï¼ä½ å¿
须为该类åå®ç°DerefåDerefMutï¼
use std::ops::{Deref, DerefMut};
impl<T> Deref for Selector<T> {
type Target = T;
fn deref(&self) -> &T {
&self.elements[self.current]
}
}
impl<T> DerefMut for Selector<T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.elements[self.current]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
æäºè¿äºå®ç°ï¼ä½ å¯ä»¥åè¿æ ·ä½¿ç¨Selectorï¼
let mut s = Selector { elements: vec!['x', 'y', 'z'], current: 2 };
// å 为`Selector`å®ç°äº`Deref`ï¼æä»¬å¯ä»¥ä½¿ç¨`*`è¿ç®ç¬¦æ¥å¼ç¨å
¶å½åå
ç´ ã
assert_eq!(*s, 'z');
// éè¿è§£å¼ç¨å¼ºå¶è½¬æ¢ï¼ç´æ¥å¨`Selector`ä¸ä½¿ç¨`char`çæ¹æ³ï¼æè¨`'z'`æ¯åæ¯ã
assert!(s.is_alphabetic());
// éè¿å¯¹`Selector`çå¼ç¨ç®æ èµå¼ï¼å°`'z'`æ¹ä¸º`'w'`ã
*s = 'w';
assert_eq!(s.elements, ['x', 'y', 'w']);
2
3
4
5
6
7
8
DerefåDerefMutç¹æ§æ¯ä¸ºå®ç°æºè½æéç±»åï¼å¦BoxãRcåArcï¼ï¼ä»¥åé£äºä½ä¸ºä½ ç»å¸¸éè¿å¼ç¨ä½¿ç¨çç±»åçæ¥ææææçæ¬ï¼å°±åVec<T>åStringå嫿¯[T]åstrçæ¥ææææçæ¬ï¼è设计çãä½ ä¸åºä»
ä»
为äºè®©Targetç±»åçæ¹æ³èªå¨åºç°å¨ä½ çç±»åä¸ï¼å°±åC++ä¸åºç±»çæ¹æ³å¨åç±»ä¸å¯è§é£æ ·ï¼è为ä¸ä¸ªç±»åå®ç°DerefåDerefMutãè¿å¹¶ä¸æ»æ¯è½å¦ä½ ææ¿å°å·¥ä½ï¼èä¸ä¸æ¦åºç°é®é¢ä¼ä»¤äººå°æã
è§£å¼ç¨å¼ºå¶è½¬æ¢æä¸ä¸ªå¯è½ä¼è®©äººæå°å°æç注æäºé¡¹ï¼Ruståºç¨å®ä»¬æ¥è§£å³ç±»åå²çªï¼ä½ä¸ä¼ç¨å®ä»¬æ¥æ»¡è¶³ç±»ååéç约æãä¾å¦ï¼ä»¥ä¸ä»£ç è¿è¡æ£å¸¸ï¼
let s = Selector { elements: vec!["good", "bad", "ugly"], current: 2 };
fn show_it(thing: &str) { println!("{}", thing); }
show_it(&s);
2
3
å¨show_it(&s)è¿ä¸ªè°ç¨ä¸ï¼Rustçå°åæ°ç±»å为&Selector<&str>ï¼è彿°åæ°ç±»å为&strï¼å®ä¼æ¾å°Deref<Target=str>çå®ç°ï¼å¹¶æ ¹æ®éè¦å°è°ç¨æ¹å为show_it(s.deref())ã
ç¶èï¼å¦æä½ å°show_itæ¹ä¸ºä¸ä¸ªæ³å彿°ï¼Rustå°±çªç¶ä¸é
åäºï¼
use std::fmt::Display;
fn show_it_generic<T: Display>(thing: T) { println!("{}", thing); }
show_it_generic(&s);
2
3
Rust伿¥éï¼
error: `Selector<&str>` doesn't implement `std::fmt::Display`
|
33 | fn show_it_generic<T: Display>(thing: T) { println!("
{}", thing); }
| ------- required by this bound in `show_it_generic`
34 | show_it_generic(&s);
| ^^ `Selector<&str>` cannot be formatted with the
| &*s
2
3
4
5
6
7
8
è¿å¯è½ä¼è®©äººæå°å°æï¼ä¸ºä»ä¹å°å½æ°æ³ååä¼å¼å
¥é误å¢ï¼ç¡®å®ï¼Selector<&str>æ¬èº«æ²¡æå®ç°Displayï¼ä½å®è§£å¼ç¨åå¾å°ç&strè¯å®å®ç°äºã
ç±äºä½ ä¼ éçåæ°ç±»åæ¯&Selector<&str>ï¼è彿°çåæ°ç±»åæ¯&Tï¼æä»¥ç±»ååéTå¿
é¡»æ¯Selector<&str>ãç¶åï¼Rust伿£æ¥T: Displayè¿ä¸ªçº¦ææ¯å¦æ»¡è¶³ï¼ç±äºå®ä¸ä¼åºç¨è§£å¼ç¨å¼ºå¶è½¬æ¢æ¥æ»¡è¶³ç±»ååéç约æï¼æä»¥è¿ä¸ªæ£æ¥å¤±è´¥äºã
为äºè§£å³è¿ä¸ªé®é¢ï¼ä½ å¯ä»¥ä½¿ç¨asè¿ç®ç¬¦æç¡®ååºå¼ºå¶è½¬æ¢ï¼
show_it_generic(&s as &str);
æè
ï¼æç
§ç¼è¯å¨ç建议ï¼ä½¿ç¨&*æ¥å¼ºå¶è¿è¡è½¬æ¢ï¼
show_it_generic(&*s);
# Default
æäºç±»åå
·æç¸å½ææ¾çé»è®¤å¼ï¼é»è®¤çåéæå符串为空ï¼é»è®¤çæ°åæ¯é¶ï¼é»è®¤çOptionæ¯Noneççãè¿ç±»ç±»åå¯ä»¥å®ç°std::default::Defaultç¹æ§ï¼
trait Default {
fn default() -> Self;
}
2
3
defaultæ¹æ³åªæ¯è¿åä¸ä¸ªæ°çSelfç±»åçå¼ãString对Defaultçå®ç°å¾ç´è§ï¼
impl Default for String {
fn default() -> String {
String::new()
}
}
2
3
4
5
Rustçææéåç±»åï¼å¦VecãHashMapãBinaryHeapççï¼é½å®ç°äºDefaultï¼å
¶defaultæ¹æ³è¿åä¸ä¸ªç©ºéåãå½ä½ éè¦æå»ºä¸ä¸ªå¼çéåï¼ä½åæ³è®©è°ç¨è
å³å®å
·ä½æå»ºåªç§éåæ¶ï¼è¿ä¼å¾æå¸®å©ãä¾å¦ï¼Iteratorç¹æ§çpartitionæ¹æ³ä¼ä½¿ç¨ä¸ä¸ªéå
æ¥å³å®è¿ä»£å¨çæçå¼çå»åï¼å°è¿äºå¼åå²å°ä¸¤ä¸ªéåä¸ï¼
use std::collections::HashSet;
let squares = [4, 9, 16, 25, 36, 49, 64];
let (powers_of_two, impure): (HashSet<i32>, HashSet<i32>) = squares.iter().partition(|&n| n & (n - 1) == 0);
assert_eq!(powers_of_two.len(), 3);
assert_eq!(impure.len(), 4);
2
3
4
5
6
éå
|&n| n & (n - 1) == 0éè¿ä½è¿ç®æ¥è¯å«2ç广¬¡æ¹æ°ï¼partitionæ¹æ³å©ç¨è¿ä¸ªéå
çæäºä¸¤ä¸ªHashSetãå½ç¶ï¼partitionå¹¶ä¸å±éäºHashSetï¼åªè¦éåç±»åå®ç°äºDefaultï¼ç¨äºçæä¸ä¸ªç©ºéåä½ä¸ºèµ·å§ï¼åExtend<T>ï¼ç¨äºåéå䏿·»å ä¸ä¸ªTç±»åçå¼ï¼ï¼ä½ å°±å¯ä»¥ç¨å®çæä»»ä½ä½ æ³è¦çéåãStringå®ç°äºDefaultåExtend<char>ï¼æä»¥ä½ å¯ä»¥è¿æ ·åï¼
let (upper, lower): (String, String) = "Great Teacher Onizuka".chars().partition(|&c| c.is_uppercase());
assert_eq!(upper, "GTO");
assert_eq!(lower, "reat eacher nizuka");
2
3
Defaultçå¦ä¸ä¸ªå¸¸è§ç¨éæ¯ä¸ºè¡¨ç¤ºå¤§éåæ°çç»æä½çæé»è®¤å¼ï¼å
¶ä¸å¤§å¤æ°åæ°ä½ é常ä¸éè¦æ´æ¹ãä¾å¦ï¼gliumåºä¸ºå¼ºå¤§è夿çOpenGLå¾å½¢åºæä¾äºRustç»å®ãglium::DrawParametersç»æä½å
å«24ä¸ªåæ®µï¼æ¯ä¸ªå段æ§å¶OpenGL渲æå¾å½¢çä¸åç»èãgliumçdraw彿°ææä¸ä¸ªDrawParametersç»æä½ä½ä¸ºåæ°ãç±äºDrawParameterså®ç°äºDefaultï¼ä½ å¯ä»¥å建ä¸ä¸ªå¹¶ä¼ éç»draw彿°ï¼åªéè¦æå®ä½ æ³è¦æ´æ¹çåæ®µï¼
let params = glium::DrawParameters {
line_width: Some(0.02),
point_size: Some(0.02),
..Default::default()
};
target.draw(..., ¶ms).unwrap();
2
3
4
5
6
è¿ä¼è°ç¨Default::default()æ¥å建ä¸ä¸ªDrawParameterså¼ï¼å
¶ææå段é½åå§å为é»è®¤å¼ï¼ç¶å使ç¨ç»æä½ç..è¯æ³å建ä¸ä¸ªæ°çDrawParameterså¼ï¼åªæ´æ¹line_widthåpoint_sizeåæ®µï¼åå¤å¥½å°å
¶ä¼ éç»target.drawã
妿ä¸ä¸ªç±»åTå®ç°äºDefaultï¼é£ä¹æ ååºä¼èªå¨ä¸ºRc<T>ãArc<T>ãBox<T>ãCell<T>ãRefCell<T>ãCow<T>ãMutex<T>åRwLock<T>å®ç°Defaultãä¾å¦ï¼Rc<T>çé»è®¤å¼æ¯ä¸ä¸ªæåTç±»åé»è®¤å¼çRcã
妿ä¸ä¸ªå
ç»ç±»åçææå
ç´ ç±»åé½å®ç°äºDefaultï¼é£ä¹è¯¥å
ç»ç±»åä¹å®ç°Defaultï¼å
¶é»è®¤å¼æ¯ä¸ä¸ªå
嫿¯ä¸ªå
ç´ é»è®¤å¼çå
ç»ã
Rustä¸ä¼ä¸ºç»æä½ç±»åéå¼å®ç°Defaultï¼ä½å¦æä¸ä¸ªç»æä½çææå段é½å®ç°äºDefaultï¼ä½ å¯ä»¥ä½¿ç¨#[derive(Default)]èªå¨ä¸ºè¯¥ç»æä½å®ç°Defaultã
# AsRef å AsMut
å½ä¸ä¸ªç±»åå®ç°äºAsRef<T>ï¼è¿æå³çä½ å¯ä»¥é«æå°ä»å®é£éåç¨ä¸ä¸ª&TãAsMutæ¯å¯¹åºå¯åå¼ç¨çç±»ä¼¼ç¹æ§ãå®ä»¬çå®ä¹å¦ä¸ï¼
trait AsRef<T: ?Sized> {
fn as_ref(&self) -> &T;
}
trait AsMut<T: ?Sized> {
fn as_mut(&mut self) -> &mut T;
}
2
3
4
5
6
7
ä¾å¦ï¼Vec<T>å®ç°äºAsRef<[T]>ï¼Stringå®ç°äºAsRef<str>ãä½ è¿å¯ä»¥å°Stringçå
容ä½ä¸ºåèæ°ç»åç¨ï¼æä»¥Stringä¹å®ç°äºAsRef<[u8]>ã
AsRefé常ç¨äºä½¿å½æ°å¨æ¥ååæ°ç±»åæ¶æ´å çµæ´»ãä¾å¦ï¼std::fs::File::open彿°ç声æå¦ä¸ï¼
fn open<P: AsRef<Path>>(path: P) -> Result<File>
opençæ£éè¦çæ¯ä¸ä¸ª&Pathï¼è¿æ¯è¡¨ç¤ºæä»¶ç³»ç»è·¯å¾çç±»åã使äºè¿ä¸ªç¾åï¼openå¯ä»¥æ¥åä»»ä½å®è½åç¨&Pathçç±»åï¼å³ä»»ä½å®ç°äºAsRef<Path>çç±»åãè¿ç±»ç±»åå
æ¬Stringãstrãæä½ç³»ç»æ¥å£å符串类åOsStringåOsStrï¼å½ç¶è¿æPathBufåPathï¼å®æ´å表请æ¥çåºææ¡£ãè¿å°±æ¯ä¸ºä»ä¹ä½ å¯ä»¥å°å符串åé¢éä¼ éç»open彿°ï¼
let dot_emacs = std::fs::File::open("/home/jimb/.emacs")?;
æ ååºä¸ææçæä»¶ç³»ç»è®¿é®å½æ°é½ä»¥è¿ç§æ¹å¼æ¥åè·¯å¾åæ°ã对äºè°ç¨è æ¥è¯´ï¼å ¶ææç±»ä¼¼äºC++ä¸çéè½½å½æ°ï¼å°½ç®¡Rustå¨ç¡®å®åªäºåæ°ç±»å坿¥åæ¹é¢éç¨äºä¸åçæ¹æ³ã
ä½äºæ
å¹¶éè¿ä¹ç®åãå符串åé¢éæ¯&strï¼èå®ç°AsRef<Path>çç±»åæ¯strï¼æ²¡æ&ãæ£å¦æä»¬å¨ âDerefåDerefMutâ ä¸è§£éçï¼Rustä¸ä¼å°è¯ä½¿ç¨è§£å¼ç¨å¼ºå¶è½¬æ¢æ¥æ»¡è¶³ç±»ååéç约æï¼æä»¥å¨è¿éå®ä»¬ä¹å¸®ä¸ä¸å¿ã
幸è¿çæ¯ï¼æ ååºå å«äºä¸ä¸ªéç¨å®ç°ï¼
impl<'a, T, U> AsRef<U> for &'a T
where
T: AsRef<U>,
T: ?Sized,
U: ?Sized
{
fn as_ref(&self) -> &U {
(*self).as_ref()
}
}
2
3
4
5
6
7
8
9
10
æ¢å¥è¯è¯´ï¼å¯¹äºä»»ä½ç±»åTåUï¼å¦æT: AsRef<U>ï¼é£ä¹&T: AsRef<U>乿ç«ï¼åªé沿çå¼ç¨ç»§ç»æä½å³å¯ãç¹å«å°ï¼ç±äºstr: AsRef<Path>ï¼æä»¥&str: AsRef<Path>乿ç«ãä»æç§æä¹ä¸è¯´ï¼è¿æ¯ä¸ç§å¨æ£æ¥AsRefç±»ååéçº¦ææ¶è·å¾æéå½¢å¼è§£å¼ç¨å¼ºå¶è½¬æ¢çæ¹æ³ã
ä½ å¯è½ä¼è®¤ä¸ºï¼å¦æä¸ä¸ªç±»åå®ç°äºAsRef<T>ï¼å®ä¹åºè¯¥å®ç°AsMut<T>ãç¶èï¼å¨æäºæ
åµä¸è¿å¹¶ä¸åéãä¾å¦ï¼æä»¬æå°è¿Stringå®ç°äºAsRef<[u8]>ï¼è¿æ¯ææä¹çï¼å 为æ¯ä¸ªString齿ä¸ä¸ªåèç¼å²åºï¼å¯ä»¥ä½ä¸ºäºè¿å¶æ°æ®æ¥è®¿é®ã使¯ï¼Stringè¿ä¸æ¥ä¿è¯äºè¿äºåèæ¯æ ¼å¼è¯å¥½çUnicodeææ¬çUTF-8ç¼ç ï¼å¦æStringå®ç°äºAsMut<[u8]>ï¼è°ç¨è
å°±å¯ä»¥éææ´æ¹Stringçåèï¼è¿æ ·ä½ å°±ä¸è½åä¿è¯Stringæ¯æ ¼å¼è¯å¥½çUTF-8äºãåªæå½ä¿®æ¹ç»å®çTä¸ä¼è¿åç±»åçä¸åæ§æ¶ï¼ä¸ä¸ªç±»åå®ç°AsMut<T>æææä¹ã
è½ç¶AsRefåAsMutç¸å½ç®åï¼ä½æä¾æ åçãéç¨çå¼ç¨è½¬æ¢ç¹æ§å¯ä»¥é¿å
æ´å
·ä½ç转æ¢ç¹æ§çæ³æ»¥ã妿å¯ä»¥å®ç°AsRef<Foo>ï¼ä½ å°±åºè¯¥é¿å
å®ä¹èªå·±çAsFooç¹æ§ã
# Borrow å BorrowMut
std::borrow::Borrowç¹æ§ä¸AsRef类似ï¼å¦æä¸ä¸ªç±»åå®ç°äºBorrow<T>ï¼é£ä¹å®çborrowæ¹æ³å¯ä»¥é«æå°ä»å®é£éåç¨ä¸ä¸ª&Tãä½Borrowæ½å äºæ´å¤éå¶ï¼ä¸ä¸ªç±»ååªæå¨&Tçåå¸å¼åæ¯è¾æ¹å¼ä¸è¢«åç¨çå¼ç¸åæ¶ï¼æåºè¯¥å®ç°Borrow<T>ãï¼Rustä¸ä¼å¼ºå¶è¿ä¸ç¹ï¼è¿åªæ¯è¯¥ç¹æ§ææ¡£ä¸è¯´æçæå¾ãï¼è¿ä½¿å¾Borrowå¨å¤çåå¸è¡¨åæ ä¸çé®ï¼æè
å¤çå å
¶ä»åå éè¦è¿è¡å叿æ¯è¾ç弿¶å¾æä»·å¼ã
ä¾å¦ï¼ä»Stringåç¨æ¶ï¼è¿ç§åºå«å°±å¾éè¦ï¼Stringå®ç°äºAsRef<str>ãAsRef<[u8]>åAsRef<Path>ï¼ä½è¿ä¸ç§ç®æ ç±»åé常å
·æä¸åçåå¸å¼ãåªæ&stråçä¿è¯ä¸çæçStringå
·æç¸åçåå¸å¼ï¼æä»¥Stringåªå®ç°äºBorrow<str>ã
Borrowçå®ä¹ä¸AsRefç¸åï¼åªæ¯åç§°ä¸åï¼
trait Borrow<Borrowed: ?Sized> {
fn borrow(&self) -> &Borrowed;
}
2
3
Borrowæ¯ä¸ºè§£å³æ³ååå¸è¡¨åå
¶ä»å
³èéåç±»åçç¹å®æ
åµè设计çãä¾å¦ï¼åè®¾ä½ æä¸ä¸ªstd::collections::HashMap<String, i32>ï¼ç¨äºå°å符串æ å°å°æ°åãè¿ä¸ªè¡¨ç鮿¯Stringç±»åï¼æ¯ä¸ªæ¡ç®é½æ¥æä¸ä¸ªStringãå¨è¿ä¸ªè¡¨ä¸æ¥æ¾æ¡ç®çæ¹æ³ç¾ååºè¯¥æ¯ä»ä¹æ ·çå¢ï¼ä¸é¢æ¯ç¬¬ä¸æ¬¡å°è¯ï¼
impl<K, V> HashMap<K, V>
where
K: Eq + Hash
{
fn get(&self, key: K) -> Option<&V> { ... }
}
2
3
4
5
6
è¿çèµ·æ¥å¾åçï¼è¦æ¥æ¾ä¸ä¸ªæ¡ç®ï¼ä½ å¿
é¡»æä¾éå该表çé®ç±»åãä½å¨è¿ç§æ
åµä¸ï¼Kæ¯Stringï¼è¿ä¸ªç¾åä¼å¼ºå¶ä½ æ¯æ¬¡è°ç¨getæ¶é½æå¼ä¼ éä¸ä¸ªStringï¼è¿æ¾ç¶å¾æµªè´¹ãå®é
ä¸ï¼ä½ åªéè¦ä¸ä¸ªæåé®çå¼ç¨ï¼
impl<K, V> HashMap<K, V>
where
K: Eq + Hash
{
fn get(&self, key: &K) -> Option<&V> { ... }
}
2
3
4
5
6
è¿ç¨å¾®å¥½ä¸äºï¼ä½ç°å¨ä½ å¿
é¡»å°é®ä½ä¸º&Stringä¼ éï¼æä»¥å¦æä½ æ³æ¥æ¾ä¸ä¸ªå¸¸éå符串ï¼å°±å¿
é¡»è¿æ ·åï¼
hashtable.get(&"twenty-two".to_string())
è¿å¾èè°¬ï¼å®å¨å ä¸åé
ä¸ä¸ªStringç¼å²åºï¼å°ææ¬å¤å¶å°å
¶ä¸ï¼åªæ¯ä¸ºäºå°å
¶ä½ä¸º&Stringåç¨ï¼ä¼ éç»getï¼ç¶åå丢å¼å®ã
ä¼ éä»»ä½å¯ä»¥ä¸æä»¬çé®ç±»åè¿è¡åå¸åæ¯è¾çä¸è¥¿å°±è¶³å¤äºï¼ä¾å¦&strå°±å®å
¨å¯ä»¥ãæä»¥æç»ççæ¬æ¯è¿æ ·çï¼è¿ä¹æ¯ä½ 卿 ååºä¸ä¼çå°çï¼
impl<K, V> HashMap<K, V>
where
K: Eq + Hash
{
fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Eq + Hash
{ ... }
}
2
3
4
5
6
7
8
9
10
æ¢å¥è¯è¯´ï¼å¦æä½ å¯ä»¥å°æ¡ç®çé®åç¨ä¸º&Qï¼å¹¶ä¸å¾å°çå¼ç¨çåå¸å¼åæ¯è¾æ¹å¼ä¸é®æ¬èº«ç¸åï¼é£ä¹æ¾ç¶&Qåºè¯¥æ¯å¯æ¥åçé®ç±»åãç±äºStringå®ç°äºBorrow<str>åBorrow<String>ï¼è¿ä¸ªæç»çæ¬çgetæ¹æ³å
è®¸ä½ æ ¹æ®éè¦ä¼ é&Stringæ&strä½ä¸ºé®ã
Vec<T>å[T; N]å®ç°äºBorrow<[T]>ãæ¯ä¸ªç±»ä¼¼å符串çç±»åé½å
许åç¨å
¶ç¸åºçåçç±»åï¼Stringå®ç°äºBorrow<str>ï¼PathBufå®ç°äºBorrow<Path>ççãæ ååºä¸ææçå
³èéåç±»åé½ä½¿ç¨Borrowæ¥å³å®åªäºç±»åå¯ä»¥ä¼ éç»å®ä»¬çæ¥æ¾å½æ°ã
æ ååºå
å«ä¸ä¸ªéç¨å®ç°ï¼ä½¿å¾æ¯ä¸ªç±»åTé½å¯ä»¥ä»èªèº«åç¨ï¼T: Borrow<T>ãè¿ç¡®ä¿äº&Kå§ç»æ¯å¨HashMap<K, V>䏿¥æ¾æ¡ç®ç坿¥åç±»åã
ä¸ºäºæ¹ä¾¿èµ·è§ï¼æ¯ä¸ª&mut Tç±»åä¹å®ç°äºBorrow<T>ï¼åå¾å¸¸ä¸æ ·è¿åä¸ä¸ªå
±äº«å¼ç¨&Tãè¿å
è®¸ä½ å°å¯åå¼ç¨ä¼ éç»é忥æ¾å½æ°ï¼èæ ééæ°åç¨ä¸ä¸ªå
±äº«å¼ç¨ï¼æ¨¡æäºRusté常ä»å¯åå¼ç¨å°å
±äº«å¼ç¨çéå¼å¼ºå¶è½¬æ¢ã
BorrowMutç¹æ§æ¯Borrow对åºå¯åå¼ç¨ççæ¬ï¼
trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
fn borrow_mut(&mut self) -> &mut Borrowed;
}
2
3
对Borrowçææåæ ·éç¨äºBorrowMutã
# From å Into
std::convert::Fromåstd::convert::Intoç¹æ§è¡¨ç¤ºå°ä¸ç§ç±»åç弿¶èå¹¶è¿åå¦ä¸ç§ç±»åçå¼ç转æ¢ãAsRefåAsMutç¹æ§æ¯ä»ä¸ç§ç±»ååç¨å¦ä¸ç§ç±»åçå¼ç¨ï¼èFromåIntoåè·åå
¶åæ°çæææï¼å¯¹å
¶è¿è¡è½¬æ¢ï¼ç¶åå°ç»æçæææè¿åç»è°ç¨è
ã
å®ä»¬çå®ä¹é常对称ï¼
trait Into<T> : Sized {
fn into(self) -> T;
}
trait From<T> : Sized {
fn from(other: T) -> Self;
}
2
3
4
5
6
7
æ ååºä¼èªå¨ä¸ºæ¯ç§ç±»åå®ç°ä»èªèº«å°èªèº«çå¹³å¡è½¬æ¢ï¼æ¯ä¸ªç±»åTé½å®ç°äºFrom<T>åInto<T>ã
è½ç¶è¿ä¸¤ä¸ªç¹æ§åªæ¯æä¾äºä¸¤ç§ååä¸ä»¶äºçæ¹å¼ï¼ä½å®ä»¬æä¸åçç¨éã
ä½ é常使ç¨Intoæ¥ä½¿ä½ ç彿°å¨æ¥ååæ°æ¶æ´å çµæ´»ãä¾å¦ï¼å¦æä½ è¿æ ·åï¼
use std::net::Ipv4Addr;
fn ping<A>(address: A) -> std::io::Result<bool>
where
A: Into<Ipv4Addr>
{
let ipv4_address = address.into();
...
}
2
3
4
5
6
7
8
9
é£ä¹ping彿°ä¸ä»
å¯ä»¥æ¥åIpv4Addrä½ä¸ºåæ°ï¼è¿å¯ä»¥æ¥åu32æ[u8; 4]æ°ç»ï¼å 为è¿äºç±»åæ°å¥½é½å®ç°äºInto<Ipv4Addr>ãï¼ææ¶å°IPv4å°åå½ä½ä¸ä¸ª32ä½ç弿ä¸ä¸ª4åèçæ°ç»å¾æç¨ãï¼å 为ping彿°åªç¥éaddresså®ç°äºInto<Ipv4Addr>ï¼æä»¥å¨è°ç¨intoæ¶ï¼ä½ ä¸éè¦æå®æ³è¦çå
·ä½ç±»åï¼åªæä¸ç§ç±»åå¯è½ææï¼æä»¥ç±»åæ¨æä¼ä¸ºä½ è¡¥å
ã
ä¸ä¸ä¸èçAsRef类似ï¼å
¶ææå¾åC++ä¸ç彿°éè½½ãæäºåé¢å®ä¹çping彿°ï¼æä»¬å¯ä»¥è¿è¡ä»¥ä¸ä»»ä½è°ç¨ï¼
println!("{:?}", ping(Ipv4Addr::new(23, 21, 68, 141))); // ä¼ éä¸ä¸ªIpv4Addr
println!("{:?}", ping([66, 146, 219, 98])); // ä¼ éä¸ä¸ª[u8; 4]
println!("{:?}", ping(0xd076eb94_u32)); // ä¼ éä¸ä¸ªu32
2
3
ç¶èï¼Fromç¹æ§èµ·çä¸åçä½ç¨ãfromæ¹æ³ä½ä¸ºä¸ä¸ªéç¨æé 彿°ï¼ç¨äºä»æä¸ªå
¶ä»åä¸å¼çæä¸ä¸ªç±»åçå®ä¾ãä¾å¦ï¼Ipv4Addr没æå为from_arrayåfrom_u32çä¸¤ä¸ªæ¹æ³ï¼èæ¯ç®åå°å®ç°äºFrom<[u8;4]>åFrom<u32>ï¼è¿æ ·æä»¬å°±å¯ä»¥è¿æ ·åï¼
let addr1 = Ipv4Addr::from([66, 146, 219, 98]);
let addr2 = Ipv4Addr::from(0xd076eb94_u32);
2
æä»¬å¯ä»¥è®©ç±»åæ¨ææ¥ç¡®å®åºç¨åªä¸ªå®ç°ã
æäºåéçFromå®ç°ï¼æ ååºä¼èªå¨å®ç°ç¸åºçIntoç¹æ§ãå½ä½ å®ä¹èªå·±çç±»åæ¶ï¼å¦æå®æååæ°æé 彿°ï¼ä½ åºè¯¥å°å®ä»¬åæé对éå½ç±»åçFrom<T>å®ç°ï¼è¿æ ·ä½ ä¼èªå¨è·å¾ç¸åºçIntoå®ç°ã
å 为fromåintoè½¬æ¢æ¹æ³è·åå
¶åæ°çæææï¼æä»¥è½¬æ¢å¯ä»¥éç¨åå§å¼çèµæºæ¥æé 转æ¢åçå¼ãä¾å¦ï¼åè®¾ä½ è¿æ ·åï¼
let text = "Beautiful Soup".to_string();
let bytes: Vec<u8> = text.into();
2
String对Into<Vec<u8>>çå®ç°åªæ¯è·åStringçå ç¼å²åºï¼å¹¶å°å
¶åå°ä¸å¨å°éæ°ç¨ä½è¿ååéçå
ç´ ç¼å²åºãè¿ç§è½¬æ¢æ éåé
æå¤å¶ææ¬ãè¿æ¯ç§»å¨æä½å®ç°é«æè½¬æ¢çå¦ä¸ä¸ªä¾åã
è¿äºè½¬æ¢è¿æä¾äºä¸ç§å¾å¥½çæ¹å¼ï¼å¨ä¸åå¼±åéç±»åä¿è¯çæ
åµä¸ï¼å°åéç±»åçå¼è½¬æ¢ä¸ºæ´çµæ´»çç±»åãä¾å¦ï¼Stringä¿è¯å
¶å
容å§ç»æ¯ææçUTF-8ï¼å
¶å¯åæ¹æ³åå°ä¸¥æ ¼éå¶ï¼ä»¥ç¡®ä¿ä½ åç任使ä½é½ä¸ä¼å¼å
¥é误çUTF-8ãä½å¨è¿ä¸ªä¾åä¸ï¼å®ææå°å°Stringâé级â为ä¸åæ®éåèï¼ä½ å¯ä»¥å¯¹å
¶è¿è¡ä»»ä½æä½ï¼ä¹è®¸ä½ è¦å¯¹å®è¿è¡åç¼©ï¼æè
å°å®ä¸å
¶ä»ä¸æ¯UTF-8çäºè¿å¶æ°æ®ç»åãå 为intoæå¼è·åå
¶åæ°ï¼è½¬æ¢åtextä¸ååå§åï¼è¿æå³çæä»¬å¯ä»¥èªç±è®¿é®ä¹åStringçç¼å²åºï¼èä¸ä¼ç ´åä»»ä½ç°æçStringã
ç¶èï¼å»ä»·è½¬æ¢å¹¶ä¸æ¯IntoåFromç约å®å
容ãè½ç¶AsRefåAsMut转æ¢é¢ææ¯å»ä»·çï¼ä½FromåInto转æ¢å¯è½ä¼åé
å
åãå¤å¶æ°æ®æä»¥å
¶ä»æ¹å¼å¤çå¼çå
容ãä¾å¦ï¼Stringå®ç°äºFrom<&str>ï¼å®ä¼å°å符串åçå¤å¶å°ä¸ºStringæ°åé
çå ç¼å²åºä¸ãstd::collections::BinaryHeap<T>å®ç°äºFrom<Vec<T>>ï¼å®ä¼æ ¹æ®å
¶ç®æ³è¦æ±å¯¹å
ç´ è¿è¡æ¯è¾åéæ°æåºã
?è¿ç®ç¬¦ä½¿ç¨FromåIntoæ¥å¸®å©æ¸
çå¯è½ä»¥å¤ç§æ¹å¼å¤±è´¥ç彿°ä¸ç代ç ï¼å¨éè¦æ¶èªå¨å°ç¹å®çé误类å转æ¢ä¸ºéç¨é误类åã
ä¾å¦ï¼å设æä¸ä¸ªç³»ç»éè¦è¯»åäºè¿å¶æ°æ®ï¼å¹¶å°å
¶ä¸ä¸é¨å以UTF-8ææ¬å½¢å¼è¡¨ç¤ºçåè¿å¶æ°åè¿è¡è½¬æ¢ãè¿æå³çè¦ä½¿ç¨std::str::from_utf8åi32çFromStrå®ç°ï¼å®ä»¬åèªå¯è½è¿åä¸åç±»åçé误ãå设æä»¬ä½¿ç¨å¨ç¬¬7ç« è®¨è®ºé误å¤çæ¶å®ä¹çGenericErroråGenericResultç±»åï¼?è¿ç®ç¬¦ä¼ä¸ºæä»¬è¿è¡è½¬æ¢ï¼
type GenericError = Box<dyn std::error::Error + Send + Sync +'static>;
type GenericResult<T> = Result<T, GenericError>;
fn parse_i32_bytes(b: &[u8]) -> GenericResult<i32> {
Ok(std::str::from_utf8(b)?.parse::<i32>()?)
}
2
3
4
5
6
ä¸å¤§å¤æ°é误类å䏿 ·ï¼Utf8ErroråParseIntErrorå®ç°äºErrorç¹æ§ï¼æ ååºä¸ºæä»¬æä¾äºä¸ä¸ªéç¨çFromå®ç°ï¼ç¨äºå°ä»»ä½å®ç°äºErrorçç±»å转æ¢ä¸ºBox<dyn Error>ï¼?è¿ç®ç¬¦ä¼èªå¨ä½¿ç¨è¿ä¸ªå®ç°ï¼
impl<'a, E: Error + Send + Sync + 'a> From<E>
for Box<dyn Error + Send + Sync + 'a> {
fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
Box::new(err)
}
}
2
3
4
5
6
è¿å°åæ¬å¯è½éè¦ä¸¤ä¸ªmatchè¯å¥çç¸å½é¿ç彿°åæäºä¸è¡ä»£ç ã
å¨FromåInto被添å å°æ ååºä¹åï¼Rust代ç ä¸å
满äºç¹å®äºå个类åç临æ¶è½¬æ¢ç¹æ§åæé æ¹æ³ãFromåIntoå°è¿äºçº¦å®è§èåï¼ä½ å¯ä»¥éµå¾ªè¿äºçº¦å®ï¼ä½¿ä½ çç±»åæ´æäºä½¿ç¨ï¼å ä¸ºä½ çç¨æ·å·²ç»çæå®ä»¬äºãå
¶ä»åºåè¯è¨æ¬èº«ä¹å¯ä»¥ä¾èµè¿äºç¹æ§ï¼å°å
¶ä½ä¸ºä¸ç§è§èçãæ ååç转æ¢ç¼ç æ¹å¼ã
FromåIntoæ¯ä¸å¯å¤±è´¥çç¹æ§ââå®ä»¬çAPIè¦æ±è½¬æ¢ä¸ä¼å¤±è´¥ãä¸å¹¸çæ¯ï¼è®¸å¤è½¬æ¢æ¯è¿æ´å¤æãä¾å¦ï¼åi64è¿æ ·çå¤§æ´æ°å¯ä»¥å卿¯i32大å¾å¤çæ°åï¼å¦ææ²¡æä¸äºé¢å¤ä¿¡æ¯ï¼å°å2_000_000_000_000i64è¿æ ·çæ°å转æ¢ä¸ºi32就没æå¤å¤§æä¹ãè¿è¡ç®åçä½è¿ç®è½¬æ¢ï¼å³ä¸¢å¼å32ä½ï¼é常ä¸ä¼å¾å°æä»¬ææçç»æï¼
let huge = 2_000_000_000_000i64;
let smaller = huge as i32;
println!("{}", smaller); // -1454759936
2
3
å¤çè¿ç§æ 嵿å¾å¤éæ©ãæ ¹æ®å ·ä½æ åµï¼è¿æ ·çâç¯ç»â转æ¢å¯è½æ¯åéçãå¦ä¸æ¹é¢ï¼åæ°åä¿¡å·å¤çåæ§å¶ç³»ç»è¿æ ·çåºç¨ï¼é常å¯ä»¥éç¨â饱åâ转æ¢ï¼å³å¤§äºæå¤§å¯è½å¼çæ°å被éå¶ä¸ºè¯¥æå¤§å¼ã
# TryFrom å TryInto
ç±äºä¸æ¸
æ¥è¿æ ·ç转æ¢åºè¯¥å¦ä½è¡¨ç°ï¼Rust没æä¸ºi32å®ç°From<i64>ï¼ä¹æ²¡æä¸ºä»»ä½å
¶ä»å¯è½ä¼ä¸¢å¤±ä¿¡æ¯çæ°å¼ç±»åä¹é´è¿è¡è½¬æ¢å®ç°Fromãç¸åï¼i32å®ç°äºTryFrom<i64>ã
TryFromåTryIntoæ¯FromåIntoçå¯å¤±è´¥çæ¬ï¼å®ä»¬åæ ·æ¯ç¸äºå¯¹åºçï¼å®ç°äºTryFromä¹å°±æå³çå®ç°äºTryIntoã
å®ä»¬çå®ä¹åªæ¯FromåIntoç¨å¾®å¤æä¸ç¹ã
pub trait TryFrom<T> : Sized {
type Error;
fn try_from(value: T) -> Result<Self, Self::Error>;
}
pub trait TryInto<T> : Sized {
type Error;
fn try_into(self) -> Result<T, Self::Error>;
}
2
3
4
5
6
7
8
9
try_into()æ¹æ³è¿åä¸ä¸ªResultï¼è¿æ ·æä»¬å°±å¯ä»¥å¨å¼å¸¸æ
åµä¸ï¼æ¯å¦æ°åå¤ªå¤§æ æ³æ¾å
¥ç»æç±»åï¼éæ©å¦ä½å¤çï¼
use std::convert::TryInto;
// æº¢åºæ¶é¥±åå¤çï¼è䏿¯ç¯ç»
let smaller: i32 = huge.try_into().unwrap_or(i32::MAX);
2
3
妿æä»¬è¿æ³å¤çè´æ°æ
åµï¼å¯ä»¥ä½¿ç¨Resultçunwrap_or_else()æ¹æ³ï¼
let smaller: i32 = huge.try_into().unwrap_or_else(|_| {
if huge >= 0 {
i32::MAX
} else {
i32::MIN
}
});
2
3
4
5
6
7
ä¸ºä½ èªå·±çç±»åå®ç°å¯å¤±è´¥ç转æ¢ä¹å¾å®¹æãErrorç±»åå¯ä»¥æ ¹æ®å
·ä½åºç¨çéæ±ï¼ç®åæå¤æãæ ååºä½¿ç¨ä¸ä¸ªç©ºç»æä½ï¼é¤äºè¡¨æåçäºé误ä¹å¤ä¸æä¾ä»»ä½ä¿¡æ¯ï¼å 为å¯ä¸å¯è½çéè¯¯å°±æ¯æº¢åºãå¦ä¸æ¹é¢ï¼æ´å¤æç±»åä¹é´ç转æ¢å¯è½æ³è¦è¿åæ´å¤ä¿¡æ¯ï¼
impl TryInto<LinearShift> for Transform {
type Error = TransformError;
fn try_into(self) -> Result<LinearShift, Self::Error> {
if!self.normalized() {
return Err(TransformError::NotNormalized);
}
...
}
}
2
3
4
5
6
7
8
9
FromåIntoç¨äºç®å转æ¢çç±»åå
³èï¼èTryFromåTryIntoå¨FromåInto转æ¢çç®åæ§åºç¡ä¸ï¼éè¿Resultæä¾äºæ´å
·è¡¨è¾¾æ§çé误å¤çè½åãè¿åä¸ªç¹æ§å¯ä»¥ä¸èµ·ä½¿ç¨ï¼å¨å个åºä¸å
³èå¤ç§ç±»åã
# ToOwned
ç»å®ä¸ä¸ªå¼ç¨ï¼é常æ
åµä¸ï¼å¦æè¯¥ç±»åå®ç°äºstd::clone::Cloneï¼å¯ä»¥éè¿è°ç¨cloneæ¥çæå
¶å¼ç¨ç®æ çæ¥ææææç坿¬ã使¯ï¼å¦æä½ æ³å
éä¸ä¸ª&stræ&[i32]ä¼ææ ·å¢ï¼ä½ å¯è½æ³è¦çæ¯ä¸ä¸ªStringæVec<i32>ï¼ä½Cloneçå®ä¹ä¸å
è®¸è¿æ ·åï¼æ ¹æ®å®ä¹ï¼å
éä¸ä¸ª&Tå¿
é¡»å§ç»è¿åä¸ä¸ªTç±»åçå¼ï¼èstrå[u8]æ¯æªç¡®å®å¤§å°çç±»åï¼å®ä»¬çè³ä¸æ¯å½æ°å¯ä»¥è¿åçç±»åã
std::borrow::ToOwnedç¹æ§æä¾äºä¸ç§æ´å®½æ¾çæ¹å¼ï¼å°å¼ç¨è½¬æ¢ä¸ºæ¥ææææçå¼ï¼
trait ToOwned {
type Owned: Borrow<Self>;
fn to_owned(&self) -> Self::Owned;
}
2
3
4
ä¸cloneå¿
须精确è¿åSelfä¸åï¼to_ownedå¯ä»¥è¿åä»»ä½è½åç¨&Selfçç±»åï¼Ownedç±»åå¿
é¡»å®ç°Borrow<Self>ãä½ å¯ä»¥ä»Vec<T>åç¨&[T]ï¼æä»¥åªè¦Tå®ç°äºCloneï¼ä»¥ä¾¿æä»¬å¯ä»¥å°åççå
ç´ å¤å¶å°åéä¸ï¼ï¼[T]å°±å¯ä»¥å®ç°ToOwned<Owned=Vec<T>>ãåæ ·ï¼strå®ç°äºToOwned<Owned=String>ï¼Pathå®ç°äºToOwned<Owned=PathBuf>ççã
# Borrow å ToOwned çåºç¨ï¼å®ç¨ç Cow
å
åå©ç¨Rustéè¦ä»ç»èèæææé®é¢ï¼æ¯å¦å½æ°åºè¯¥éè¿å¼ç¨è¿æ¯å¼æ¥æ¥æ¶åæ°ãéå¸¸ä½ å¯ä»¥éæ©å
¶ä¸ä¸ç§æ¹å¼ï¼åæ°çç±»åä¹åæ äºä½ çå³å®ãä½å¨æäºæ
åµä¸ï¼ç´å°ç¨åºè¿è¡ä½ æè½å³å®æ¯åç¨è¿æ¯æ¥ææææï¼std::borrow::Cowç±»åï¼è¡¨ç¤ºâåæ¶å
éâï¼æä¾äºä¸ç§è§£å³æ¹æ¡ã
å®çå®ä¹å¦ä¸ï¼
enum Cow<'a, B: ?Sized>
where
B: ToOwned
{
Borrowed(&'a B),
Owned(<B as ToOwned>::Owned),
}
2
3
4
5
6
7
Cow<B>è¦ä¹åç¨ä¸ä¸ªæåBçå
±äº«å¼ç¨ï¼è¦ä¹æ¥æä¸ä¸ªå¯ä»¥ä»ä¸åç¨è¿ç§å¼ç¨çå¼ã
ç±äºCowå®ç°äºDerefï¼ä½ å¯ä»¥åä½¿ç¨æåBçå
±äº«å¼ç¨ä¸æ ·å¯¹å®è°ç¨æ¹æ³ï¼å¦æå®æ¯Ownedï¼å®ä¼åç¨å¯¹æ¥æçå¼çå
±äº«å¼ç¨ï¼å¦æå®æ¯Borrowedï¼å®ç´æ¥è¿åæææçå¼ç¨ã
ä½ è¿å¯ä»¥éè¿è°ç¨to_mutæ¹æ³æ¥è·å对Cowçå¼çå¯åå¼ç¨ï¼è¯¥æ¹æ³è¿åä¸ä¸ª&mut Bã妿Cowæ°å¥½æ¯Cow::Borrowedï¼to_mutä¼ç®åå°è°ç¨å¼ç¨çto_ownedæ¹æ³æ¥è·åå¼ç¨ç®æ ç坿¬ï¼å°Cow转æ¢ä¸ºCow::Ownedï¼å¹¶åç¨å¯¹æ°æ¥æçå¼çå¯åå¼ç¨ãè¿å°±æ¯è¯¥ç±»ååç§°ææçâåæ¶å
éâè¡ä¸ºã
åæ ·ï¼Cowæä¸ä¸ªinto_ownedæ¹æ³ï¼å¦ææå¿
è¦ï¼å®ä¼å°å¼ç¨æåä¸ºæ¥ææææçå¼ï¼ç¶åè¿åå®ï¼å¨è¿ä¸ªè¿ç¨ä¸å°æææè½¬ç§»ç»è°ç¨è
å¹¶æ¶èæCowã
Cowçä¸ä¸ªå¸¸è§ç¨éæ¯è¿åä¸ä¸ªéæåé
çå符串常éæä¸ä¸ªè®¡ç®å¾å°çå符串ãä¾å¦ï¼åè®¾ä½ éè¦å°ä¸ä¸ªé误æä¸¾è½¬æ¢ä¸ºä¸æ¡æ¶æ¯ã大夿°åä½å¯ä»¥ç¨åºå®å符串å¤çï¼ä½å
¶ä¸ä¸äºå使é¢å¤çæ°æ®åºè¯¥å
å«å¨æ¶æ¯ä¸ãä½ å¯ä»¥è¿åä¸ä¸ªCow<'static, str>ï¼
use std::path::PathBuf;
use std::borrow::Cow;
fn describe(error: &Error) -> Cow<'static, str> {
match *error {
Error::OutOfMemory => "out of memory".into(),
Error::StackOverflow => "stack overflow".into(),
Error::MachineOnFire => "machine on fire".into(),
Error::Unfathomable => "machine bewildered".into(),
Error::FileNotFound(ref path) => {
format!("file not found: {}", path.display()).into()
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
è¿æ®µä»£ç 使ç¨CowçIntoå®ç°æ¥æé å¼ãè¿ä¸ªmatchè¯å¥ç大夿°åæ¯è¿åä¸ä¸ªæåéæåé
å符串çCow::Borrowedã使¯å½æä»¬éå°FileNotFoundå使¶ï¼æä»¬ä½¿ç¨format!æ¥æé ä¸ä¸ªå
å«ç»å®æä»¶åçæ¶æ¯ãè¿ä¸ªmatchåæ¯äº§çä¸ä¸ªCow::Ownedå¼ã
è°ç¨describeä¸ä¸éè¦æ´æ¹å¼çè°ç¨è
å¯ä»¥ç®åå°å°Cowå½ä½&stræ¥å¤çï¼
println!("Disaster has struck: {}", describe(&error));
éè¦æ¥ææææçå¼çè°ç¨è å¯ä»¥è½»æ¾çæä¸ä¸ªï¼
let mut log: Vec<String> = Vec::new();
...
log.push(describe(&error).into_owned());
2
3
使ç¨Cowæå©äºdescribe彿°åå
¶è°ç¨è
å°åé
æä½æ¨è¿å°å¿
è¦æ¶è¿è¡ã