1. 程式人生 > 其它 >Rust能力養成之(5):功能與方法

Rust能力養成之(5):功能與方法

圖片

前言

上一篇,介紹了Rust語言的

  • 結構體

  • 列舉

如果型別(Types)只有屬性,沒有動態行為,顯然是不夠的,在實際場景中,我們需要與型別有些互動,比如利用函式(function)或方法(method)得到返回值,或者可以對已有屬性進行操作或修改。

Rust為我們準備了 impl blocks,字面看來,就是為型別實現(implementations)點什麼,其同時適用於使用者自定義任何封裝型別

那麼,這一篇,我們介紹的函式和方法實現涉及

  • 結構體的函式和方法實現

  • 列舉的函式和方法實現

  • 模組簡介

結構體之功能實現

這裡的程式碼為之前寫過的Player 結構新增兩個功能:

  • 第9行:記住impl這個關鍵字

  • 第10-16行:一個類似於建構函式的函式(dong xi),接受名稱併為Person中的其餘欄位設定預設值

  • 第18-24行:兩個方法函式,get_friends和set_friends,分別負責取名和取數

//struct_methods.rs
structPlayer{name:String,iq:u8,friends:u8}
implPlayer{fnwith_name(name:&str)->Player{Player{name:name.to_string(),iq:100,friends:100}}
fnget_friends(&self)->u8{
self.friends} fnset_friends(&mutself,count:u8){self.friends=count;}} fnmain(){letmutplayer=Player::with_name("Dave");player.set_friends(23);println!("{}'sfriendscount:{}",player.name,player.get_friends());//anotherwaytocallinstancemethods.let_=Player::get_friends(&player);}

程式碼結果為:

圖片

在寫實現的時候,通常會有兩種方法(methods)可寫:

  • Associated methods:這種方法,不需要self 型別作為第一引數,上面示例中的with_name 方法就是這種,類似於面向物件程式設計中的靜態方法(static method),可以認為這種方法是自身具足的,參見第28行

  • Instance methods:該方法以self為第一引數,與Python類似,因此只能藉由例項(instance)喚起,參見第29行,而第32行提供了另一種呼叫該類方法的方式(讀者可以自己試一下,如果不用指標型別作為引數,會出現什麼情況?)

再看一下 set_friends方法是引數 &mut self,表明self是在執行時從型別例項中借用過來的,如果不用&,則會把例項的值賦給該方法,等執行之後,又會重新釋放。

讀到這裡,好像有點不知所云,請讀者記住這一點,很快就會在記憶體管理與安全的部分給大家一個交代。

列舉之功能實現

這裡進入列舉部分,看一個有關支付的程式碼示例,​​​​​​​

// enum_methods.rs
enumPaymentMode{Debit,Credit,Paypal}
//Bunchofdummypaymenthandlers
fnpay_by_credit(amt:u64){println!("Processingcreditpaymentof{}",amt);}fnpay_by_debit(amt:u64){println!("Processingdebitpaymentof{}",amt);}fnpaypal_redirect(amt:u64){println!("Redirectingtopaypalforamount:{}",amt);}
implPaymentMode{fnpay(&self,amount:u64){matchself{PaymentMode::Debit=>pay_by_debit(amount),PaymentMode::Credit=>pay_by_credit(amount),PaymentMode::Paypal=>paypal_redirect(amount)}}}
fnget_saved_payment_mode()->PaymentMode{PaymentMode::Debit}
fnmain(){letpayment_mode=get_saved_payment_mode();payment_mode.pay(512);}

程式碼結果如下

圖片

以上程式碼非常明朗,這裡的實現方法名稱為:get_saved_payment_mode()用來返回使用者的付款模式:Credit Card, Debit Card, or Paypal顯然很適合用列舉建模,這3種模式顯然作為列舉變體。

在pay方法中,使用者可以任選三種付款方式之一進行支付,該方法對應決定使用哪一種,而後進行指派。請讀者最後自己按照具體場景,敲一下這個程式碼,相信會感到這裡面列舉所起到的作用是非常有恰當的。

進一步說來,列舉廣泛用於狀態機建模,當與match語句結合使用時,可以使狀態轉換程式碼編寫起來非常簡潔;還可以用於自定義錯誤型別方面的建模。

當enum變數沒有與之關聯的任何資料時,可以像C列舉那樣使用,其中的變數隱式的具有從0開始的整數值,但也可以手動標記為整數值(isize),而這在與外部C庫互動時還是很有用的。

模組(modules)簡介

任何程式語言都會提供一種方法,將相對繁重的程式碼拆分為多個檔案,以管理複雜性,Rust使用模組來做這件事,有關模組的詳細介紹,會放在本系列的第二部分。這裡列出一些重點,作為本部分後續章節的基礎。

  • 每個Rust程式都需要有一個root模組。在可執行檔案中,通常是main.rs,對於libraries,是libraries .rs

  • 模組可以在其他模組中宣告,也可以作為檔案和目錄

  • root模組要使用mod關鍵字來宣告,以保證編譯器可以識別

  • 要使用模組內的任何專案,需要使用use關鍵字以及模組的名稱來引用

  • 模組中定義的專案預設情況下是私有的,需要使用pub關鍵字將其公開

結語

可以看出,本篇與上一篇形成一一對應,上一篇重點在於如何定義結構體和列舉的屬性,本篇介紹瞭如何與這兩種使用者自定義型別進行互動,並對之進行操作,而使這些程式碼編寫變得靈活,表現力充分增強,效果自然可期。難怪某位Rust中文社群的一位資深成員談及:這麼多年了,Rust讓我又感到了程式設計的樂趣。

下一篇,我們看下集合體與迭代器

主要參考和建議讀者進一步閱讀的文獻

https://doc.rust-lang.org/book

1.Rust程式設計之道,2019, 張漢東

2.The Complete Rust Programming Reference Guide,2019, Rahul Sharma,Vesa Kaihlavirta,Claus Matzinger

3.Hands-On Data Structures and Algorithms with Rust,2018,Claus Matzinger

4.Beginning Rust ,2018,Carlo Milanesi

5.Rust Cookbook,2017,Vigneshwer Dhinakaran