rust-方法語法

方法語法

方法類似于函數:我們用 fn 關鍵字和一個名稱來聲明它們,它們可以有參數和返回值,并且包含一些在從其他地方調用該方法時運行的代碼。與函數不同,方法是在結構體(或枚舉、trait 對象,分別在第6章和第18章介紹)上下文中定義的,其第一個參數總是 self,代表調用該方法的結構體實例。

定義方法

讓我們將接收 Rectangle 實例作為參數的 area 函數改為定義在 Rectangle 結構體上的 area 方法,如清單5-13所示。

文件名: src/main.rs

#[derive(Debug)]
struct Rectangle {width: u32,height: u32,
}impl Rectangle {fn area(&self) -> u32 {self.width * self.height}
}fn main() {let rect1 = Rectangle {width: 30,height: 50,};println!("The area of the rectangle is {} square pixels.",rect1.area());
}

清單5-13:在Rectangle結構體上定義area方法
為了在Rectangle上下文中定義函數,我們開始了一個針對Rectangle的 impl(實現)塊。這個 impl 塊中的所有內容都與類型 Rectangle 相關聯。然后我們把 area 函數移到 impl 的大括號內,并將簽名中的第一個(也是唯一一個)參數改為 self,同時函數體內也相應替換。在 main 中,我們原本調用傳入 rect1 參數的 area 函數,現在可以使用方法語法直接對我們的 Rectangle 實例調用 area 方法。方法語法寫在實例后面:加點,再跟上方法名、括號及任何參數。

area 的簽名里使用 &self 而不是 rectangle: &Rectangle。&self 實際上是 self: &Self 的簡寫。在 impl 塊中,Self 是當前實現塊對應類型的別名。所有的方法必須以名字為 self 且類型為 Self 的參數作為首個參數,因此 Rust 允許你只寫成 self 來簡化書寫。但注意仍需加 & 表明此處借用了 Self 實例,就像之前用 rectangle: &Rectangle 一樣。方法可以取得 self 所有權,也可以不可變借用自我(如這里),或者可變借用自我,就像對待其它任意參數一樣。

這里選擇 &self 和之前函數版本里的 &Rectangle 原因相同:不想獲取所有權,只想讀取結構體數據而非修改。如果希望改變被調用實例,則首個參數應設為 &mut self。而僅以 self 為首參并取得所有權的方法較少見;通常用于將自身轉換成另一種東西,從而阻止調用者繼續使用原始實例。

除了提供更方便的方法語法、不必每次重復指定自我類型外,使用方法代替普通函數最主要原因是組織性好——把能作用于某一類型實例的一切功能集中放進同一 impl 塊,而不用讓未來用戶去庫里各處尋找該類型能力所在。

注意,可以給某個字段起同樣名字的方法。例如,可以給 Rectangle 定義一個也叫 width 的方法:

文件名: src/main.rs

impl Rectangle {fn width(&self) -> bool {self.width > 0}
}fn main() {let rect1 = Rectangle {width: 30,height: 50,};if rect1.width() {println!("The rectangle has a nonzero width; it is {}", rect1.width);}
}

這里,我們讓寬度(width)這個同名的方法判斷如果實例字段width大于0則返回 true,否則 false;即使名稱相同,在該命名空間下,該字段依然可用于任何目的。在 main 中,當跟著圓點后帶括號時,比如 rect1.width() ,Rust 知道指的是寬度這個“方法”;當沒有括號時,比如 rect1.width ,Rust 知道指的是字段本身。

通常但不總是如此,當給字段起同樣名字的方法時,這類“getter”只會返回對應字段值,不做其它操作。而 Rust 并不會自動幫 struct 字段生成 getter 方法,這一點與某些語言不同。這類 getter 很實用,因為你可以把字段設置成私有,但公開對應 getter,使得外部只能讀不能改,這是設計公共 API 時常見手段。本書將在第7章講解什么是公有(private)、私有(public),以及如何標記成員訪問權限。

-> 操作符去哪兒了?
C 和 C++ 調用對象上的成員或其指針上的成員分別需要 . 和 -> 兩種操作符,即若 object 是指針,則 object->something() 等價于 (*object).something() 。

Rust 沒有等價于 -> 操作符,而采用了一種稱作自動引用和解引用(automatic referencing and dereferencing)的新特性。這也是 Rust 少數幾個支持這種行為的位置之一——即調用對象上的某個 method 時,如果簽名要求引用或可變引用甚至取值,會自動幫你補充 &, &mut 或 * 。

例如下面兩句完全等效:

p1.distance(&p2);
(&p1).distance(&p2);

第一句看起來更簡潔。這種自動添加引用行為之所以行得通,是因為每個 method 都明確知道自己的接收者(receiver)—即那個叫做 self 參數的數據類型。有了接收者信息及 method 名稱,Rust 能準確推斷出這是讀取(&self)、修改(&mut self)還是消費(self)。這種隱式借用機制極大提升了擁有權系統實際編程體驗的人機友好度。

帶有更多參數的方法

讓我們通過在 Rectangle 結構體上實現第二個方法來練習使用方法。這次,我們希望 Rectangle 的一個實例接收另一個 Rectangle 實例作為參數,并返回 true,如果第二個矩形可以完全放入第一個矩形(self)內;否則,返回 false。也就是說,一旦定義了 can_hold 方法,我們就能像清單 5-14 中那樣編寫程序。

文件名:src/main.rs

fn main() {let rect1 = Rectangle {width: 30,height: 50,};let rect2 = Rectangle {width: 10,height: 40,};let rect3 = Rectangle {width: 60,height: 45,};println!("Can rect1 hold rect2?{}", rect1.can_hold(&rect2));println!("Can rect1 hold rect3?{}", rect1.can_hold(&rect3));
}

清單 5-14:使用尚未編寫的 can_hold 方法
預期輸出如下,因為 rect2 的兩個維度都小于 rect1,而 rect3 比 rect1 寬:

Can rect1 hold rect2? true
Can rect1 hold rect3? false

我們知道要定義一個方法,所以它會在 impl Rectangle 塊中。方法名為 can_hold,它將接受另一個不可變借用的 Rectangle 參數。通過查看調用該方法的代碼可知參數類型:rect1.can_hold(&rect2)傳入的是 &rect2,這是對 rect2(Rectangle 實例)的不可變借用。這很合理,因為我們只需要讀取 rect2(而非修改,需要可變借用),且希望 main 保留對 rect2 的所有權,以便調用完 can_hold 后還能繼續使用它。can_hold 返回值是布爾型,實現時檢查 self 的寬和高是否分別大于另一個矩形的寬和高。讓我們把新的 can_hold 方法添加到清單 5-13 中的 impl 塊,如清單 5-15 所示。

文件名:src/main.rs

impl Rectangle {fn area(&self) -> u32 {self.width * self.height}fn can_hold(&self, other: &Rectangle) -> bool {self.width > other.width && self.height > other.height}
}

清單 5-15:為接受另一個 Rectangle 實例作為參數的 can_hold 方法實現

當運行包含清單 5-14 中 main 函數的代碼時,將得到期望輸出。方法可以接受多個參數,這些參數加在 self 參數之后,其工作方式與函數中的參數相同。

關聯函數

所有定義在 impl 塊中的函數稱為關聯函數,因為它們與 impl 后面的類型相關聯。我們可以定義不以 self 為首個參數(因此不是方法)的關聯函數,因為這些函數不需要某個類型實例即可工作。例如,我們已經使用過 String 類型上的 String::from 函數就是這樣一種關聯函數。

非方法形式的關聯函數通常用于構造器,用來返回結構體的新實例。這類構造器常被命名為 new,但 new 并不是特殊名稱,也沒有內置于語言中。例如,我們可以提供一個名為 square 的關聯函數,它只有一個尺寸參數,并將其同時賦給寬和高,從而更方便地創建正方形矩形,而無需重復指定相同值:

文件名:src/main.rs

impl Rectangle {fn square(size: u32) -> Self {Self {width: size,height: size,}}
}

Self 在返回類型及函數體中是對 impl 后面出現類型(此處即 Rectangle)的別名。

調用這個關聯函數時,使用 :: 符號連接結構體名稱,例如 let sq = Rectangle::square(3); 。該功能由結構體命名空間限定符管理;:: 符號既用于關聯函數,也用于模塊創建命名空間。本書第7章將討論模塊內容。

多個 impl 塊

每個結構體允許擁有多個 impl 塊。例如,清單5-15等價于下面分開各自實現每個方法的代碼,如清單5-16所示:

impl Rectangle {fn area(&self) -> u32 {self.width * self.height}
}impl Rectangle {fn?can_hold(&self,?other:&Rectangle)?->?bool?{self.width>other.width&&self.height>other.height}
}

清單5-16:用多個impl塊重寫清單5-15

這里沒必要拆分成多個impl塊,但這種語法是合法的。在第10章講解泛型和特征時,會看到多重impl塊派上用場的時候。

總結

結構體讓你能夠創建符合領域需求、自定義含義的數據類型。利用結構體,可以把相關數據組合起來并給每部分命名,使代碼更加明晰。在 impl 塊里,你能定義與該類型相關聯的方法,其中“方法”是一種特殊形式、綁定到具體實例行為上的關聯函 數。但自定義數據類型不僅限于struct,讓我們轉向 Rust 枚舉(enum),再增加一項強力工具吧!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/90426.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/90426.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/90426.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C++】C++ 的入門語法知識1

本文主要講解C語言的入門知識,包括命名空間、C的輸入與輸出、缺省參數以及函數重載。 目錄 1 C的第一個程序 2 命名空間 1) 命名空間存在的意義 2) 命名空間的定義 3) 命名空間的使用 3 C的輸出與輸入 1) C中…

SpringBoot6-10(黑馬)

JWT令牌簡介:1.JWT全稱:JSON Web Token(https://iwt.io/)定義了一種簡潔的、自包含的格式,用于通信雙方以json數據格式安全的傳輸信息。2.組成: >第一部分:Header(頭),記錄令牌類型、簽名算法等。例如:("alg":“HS256",“t…

智能制造場景195個術語的16個分類

說明:《智能制造典型場景參考指引(2025年版)》日前,由工信部辦公廳正式發布,將成為眾多制造型企業的工作綱領 1. 工廠數字化規劃設計(1.1):在電腦上用專業軟件設計工廠布局、規劃生產…

[論文閱讀] 人工智能 + 軟件工程 | 微信閉源代碼庫中的RAG代碼補全:揭秘工業級場景下的檢索增強生成技術

微信閉源代碼庫中的RAG代碼補全:揭秘工業級場景下的檢索增強生成技術 論文標題:A Deep Dive into Retrieval-Augmented Generation for Code Completion: Experience on WeChatarXiv:2507.18515 A Deep Dive into Retrieval-Augmented Generation for Co…

RabbitMQ—仲裁隊列

上篇文章: RabbitMQ集群搭建https://blog.csdn.net/sniper_fandc/article/details/149312481?fromshareblogdetail&sharetypeblogdetail&sharerId149312481&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link 目錄 1 Raft一致性算法…

[2025CVPR-目標檢測方向] CorrBEV:多視圖3D物體檢測

1. ?研究背景與動機? 論文關注自動駕駛中相機僅有的多視圖3D物體檢測(camera-only multi-view 3D object detection)問題。盡管基于鳥瞰圖(BEV)的建模近年來取得顯著進展(如BEVFormer和SparseBEV等基準模型&#xf…

oracle 數據庫批量變更數據 將a表字段批量更新為b表字段

需求:將excel表中的數據批量更新到 taccoinfo表中vc_broker字段0、備份:create table taccoinfo0724 as select vc_custno ,vc_broker from taccoinfo 1、創建臨時表: create table taccoinfo0724_1 as select vc_custno ,vc_broker from…

vim-xcode 項目常見問題解決方案

vim-xcode 項目常見問題解決方案 項目基礎介紹 vim-xcode 是一個開源項目,旨在通過 Vim 編輯器與 Xcode 項目進行交互。該項目允許開發者在 Vim 中直接構建、測試和運行 Xcode 項目,從而提高開發效率。vim-xcode 主要使用 Vimscript 編寫,并依…

個性化網頁計數器

需要一個服務器環境來存放我們的計數器腳本和數據庫。對于初學者來說,PHP和MySQL是一個不錯的組合,因為它們易于學習且廣泛應用。接下來,我們開始編寫PHP腳本。這個腳本的主要任務是接收來自網頁的請求,并將訪問信息存儲到數據庫中…

詳解力扣高頻SQL50題之1683. 無效的推文【入門】

傳送門:1683. 無效的推文 題目 表:Tweets ----------------------- | Column Name | Type | ----------------------- | tweet_id | int | | content | varchar | ----------------------- 在 SQL 中,tweet_id 是這個表的主鍵。 content 只…

Spring Boot與Python的聯動:實戰案例解析

目錄一、背景與需求二、技術準備2.1 Spring Boot 基礎2.2 Python 環境搭建三、基于 RESTful API 的調用3.1 創建 Python Flask 應用3.2 創建 Spring Boot 應用3.3 測試與驗證四、通過 ProcessBuilder 調用 Python 腳本4.1 創建 Python 腳本4.2 Spring Boot 中調用腳本4.3 注意事…

力扣刷題(第九十七天)

靈感來源 - 保持更新,努力學習- python腳本學習密鑰格式化解題思路移除原字符串中的所有破折號,并將小寫字母轉換為大寫。從后向前遍歷處理后的字符串,每 K 個字符為一組。最后將各組逆序拼接,并用破折號分隔。class Solution:def…

ESP32入門實戰:PC遠程控制LED燈完整指南

引言:物聯網遠程控制基礎 遠程控制是物聯網應用的基礎功能之一,通過ESP32實現PC遠程控制LED燈不僅是一個經典入門項目,更是理解網絡通信、嵌入式開發和物聯網交互的絕佳實踐。本文將詳細介紹如何通過WiFi和UDP協議,從零開始構建一…

主流攝像頭協議及其開源情況,GB/T 28181協議介紹

一、主流攝像頭協議及開源情況 1. RTSP(Real Time Streaming Protocol) 技術特性:基于TCP/UDP的實時流傳輸協議,支持雙向通信(如暫停、播放控制)。應用場景:攝像頭實時監控、視頻點播系統。開源…

「iOS」——RunLoop學習

底層學習iOS--RunLoop學習RunLoop的概念RunLoop與線程的關系RunLoop的結構ModeObserverTimerSourceRunLoop 執行流程RunLoop 的應用1.AutoreleasePool是什么時候釋放的2.觸控事件的響應3.刷新界面4.線程保活小知識mach Port**Toll-Free Bridging(對象橋接&#xff0…

從零構建 Node20+pnpm+pm2 環境鏡像:基于 Dockerfile 的兩種方案及持久化配置指南

前言:在Node.js項目部署中,環境一致性和服務自動恢復是運維的核心需求。無論是本地開發還是生產部署,使用Docker封裝Node20、pnpm(高效包管理)和pm2(進程守護)環境,能避免“本地能跑…

【Python機器學習】4.3. 模型優化

喜歡的話別忘了點贊、收藏加關注哦(關注即可查看全文),對接下來的教程有興趣的可以關注專欄。謝謝喵!(・ω・) 4.3.1. 實戰中會遇到的問題 首先看一個例子: 根據任檢測數據x1x_1x1?、x2x_2x2…

Impact rating 影響等級定義(學習筆記)

影響等級可以通過四個方面定義,包含安全性safety,經濟型financial,操作性operational,和私密性privacy 即[S,F,O,P]這四個方面。每個方面又可以定義四個不同的等級,包含severe(嚴重的)&#xff…

同花順前端潛在面試題目與答案

潛在面試題目與答案 以下是根據您提供的“崗位職責”和“崗位要求”整理出的潛在面試題目和參考答案。請注意,這些答案僅供參考,您需要根據自己的實際經驗和理解進行更詳細和個性化的闡述。 一、基礎技術知識(Vue/前端工程化/HTML/CSS/JS&…

J2EE模式---組合實體模式

組合實體模式基礎概念組合實體模式(Composite Entity Pattern)是一種企業級設計模式,屬于 J2EE 模式的一種,其核心思想是將多個實體對象組合成一個更高層次的對象(組合實體),以簡化客戶端與這些…