日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Rust学习之——From Trait和Into Trait以及“类型”到字符串的转换

發(fā)布時間:2023/12/20 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Rust学习之——From Trait和Into Trait以及“类型”到字符串的转换 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一次奇怪的實踐

今天看了一個demo,為自定義類型到String類型的轉(zhuǎn)換實現(xiàn)了From Trait下的from方法,但是是調(diào)用into方法來執(zhí)行該轉(zhuǎn)換。一開始就覺得很離譜。具體如下所示:

struct OriginType{value: String, }impl From<OriginType> for TargetType {fn from (t: OriginType) -> TargetType {省略} }let o: OriginType = OriginType::new("asdad"); let t: TargetType = o.into();

然后查了資料,發(fā)現(xiàn)From和Into這兩個Trait是一對,經(jīng)常在一起出現(xiàn),但是為什么實現(xiàn)from方法卻可以直接用into調(diào)用呢?

于是我提出了如下的幾個問題:

  • 為什么可以為類型實現(xiàn)From中的from方法,卻用的是從來沒有出現(xiàn)過的into方法?
  • 那么Into Trait是干什么用的?
  • 先回答第一個問題

    Used to do value-to-value conversions while consuming the input value. It is the reciprocal of Into.

    One should always prefer implementing From over Into because implementing From automatically provides one with an implementation of Into thanks to the blanket implementation in the standard library.

    根據(jù)官網(wǎng)的描述,From和Into這兩個Trait是互為相反的(reciprocal)。并且人們應(yīng)該更喜歡優(yōu)先實現(xiàn)From,因為實現(xiàn)From會自動提供Into的實現(xiàn),這要?dú)w功于標(biāo)準(zhǔn)庫中的一攬子(blanket)實現(xiàn)。

    第二個問題

    Only implement Into when targeting a version prior to Rust 1.41 and converting to a type outside the current crate. From was not able to do these types of conversions in earlier versions because of Rust’s orphaning rules. See Into for more details.

    Into Trait只在Rust1.41之前,并且用于把一個類型轉(zhuǎn)換為當(dāng)前crate之外的類型(例如標(biāo)準(zhǔn)庫中的Vec或外部庫中的類型)。這是因為Rust有孤兒規(guī)則,不能去改動外部的,或者說是當(dāng)前crate之外的類型,而From在早期的版本中無法做到這些類型之間的轉(zhuǎn)換。

    Prefer using Into over using From when specifying trait bounds on a generic function. This way, types that directly implement Into can be used as arguments as well.

    當(dāng)在泛型函數(shù)上指定Trait bounds時,應(yīng)該優(yōu)先使用Into。稍后將在Into的用法中詳細(xì)介紹。

    From Trait

    From Trait 用于提供值與值之間的轉(zhuǎn)換(從類型OriginType到另一個類型TargetType)。

    pub trait From<T> {fn from(T) -> Self; }

    要為TargetType實現(xiàn)From,必須實現(xiàn)的方法是from??聪旅娴囊粋€例子:

    impl From<OriginType> for TargetType {fn from(value: OriginType) -> Self {// pass// 返回一個TargetType的實例} }let o: OriginType; // 這兩種方法都可以,第一種方法可以自動推斷類型,因此不需要類型注解 // 第二種方法由于使用了into方法,而且一個類型可以轉(zhuǎn)換為多個其他類型,因此必須進(jìn)行類型注解 let t = TargetType::from(o); let t: TargetType = o.into();

    實例:下面的代碼片段就是從字符串的HTTP請求 轉(zhuǎn)換為 為帶有數(shù)據(jù)結(jié)構(gòu)的、便于查詢的HttpRequest的結(jié)構(gòu)體類型。

    impl From<String> for HttpRequest {fn from (req: String) -> Self {return HttpRequest {method: parsed_method(req),resource: parsed_resource(req),version: parsed_version(req),headers: parsed_headers(req),body: parsed_body(req),}} }let req_string: String = String::from_utf8(read_buffer.to_vec()).unwrap(); // 有兩種方法第一種是實現(xiàn)的from方法,第二種是自動對應(yīng)的Into實現(xiàn)的into方法 // 第一種方法可以自動推斷類型,因此可以不寫類型注解 // 第二種方法使用了into方法,而且一個類型可以轉(zhuǎn)換為多個其他類型,因此必須進(jìn)行類型注解 let http_request = HttpRequest::from(req_string); let http_request: HttpRequest = req_string.into();

    再說Into Trait

    之前說了,在Rust1.41之前,如果目標(biāo)類型不是當(dāng)前crate中的一部分,那么不能直接實現(xiàn)From方法,例如使用以下的代碼:

    在下面的代碼片段中,Wrapper是一個自定義的元組結(jié)構(gòu)體,用于存放類型T的向量,而目標(biāo)類型Vec<T>是標(biāo)準(zhǔn)庫中的類型。

    struct Wrapper<T>(Vec<T>);impl<T> From<Wrapper<T>> for Vec<T> {fn from(w: Wrapper<T>) -> Vec<T> {w.0} }

    這段代碼在舊版本中會編譯失敗,這是因為Rust的孤兒規(guī)則曾經(jīng)更嚴(yán)格一些。要繞過這個,可以嘗試實現(xiàn)Into:

    impl Into<TargetType> for OriginType {fn into(value: OriginType) -> TargetType {// 返回TargetType類型的值} } struct Wrapper<T>(Vec<T>);impl<T> Into<Vec<T>> for Wrapper<T> {fn into(self) -> Vec<T> {self.0} }

    重要的是要了解 Into 不提供 From 實現(xiàn)( From 卻提供 Into)。因此,應(yīng)該始終嘗試先實現(xiàn) From,如果 From 無法實現(xiàn),則再嘗試使用 Into。

    標(biāo)準(zhǔn)庫中的String類型就實現(xiàn)了Into<Vec<u8>>:is_hello的參數(shù)表示可以接收任意一個能夠轉(zhuǎn)換為Vec<u8>的類型。

    fn is_hello<T: Into<Vec<u8>>>(s: T) {let bytes = b"hello".to_vec();assert_eq!(bytes, s.into()); }let s = "hello".to_string(); is_hello(s);

    注意事項

    From和Into實現(xiàn)的轉(zhuǎn)換不允許出現(xiàn)錯誤,即轉(zhuǎn)換過程不能拋出異常。如果轉(zhuǎn)換過程允許拋出異常請使用:TryFrom和TryInto。

    總結(jié)

    以上是生活随笔為你收集整理的Rust学习之——From Trait和Into Trait以及“类型”到字符串的转换的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。