Rust Trait Object 和物件安全

2021-10-12 05:04:57 字數 3006 閱讀 3148

所謂 trait 物件,可以理解為其它物件導向語言中,指向介面或基類的指標或引用。其它oo語言指向基類的指標在執行時確定其實際型別。

rust 沒有類繼承,指向 trait 的指標或引用起到類似的效果,執行時被確定具體型別。所以編譯期間不知道大小。

trait 物件體現出來就是對乙個 trait型別的指標或引用。

不是所有的 trait 都可以被當做 trait 物件使用,能作為 trait 物件使用的 trait 要同時滿足以下規則:

rule 1: trait 的 self 型別引數不能被限定為 sized (trait 不能標記為 sized )

and rule 2: trait 中的所有方法必須是 【物件安全】的

該規則要求方法滿足以下條之一

or rule 2.1: 方法受 self: sized 約束(被 sized 約束的方法不能被動態呼叫,所以能超脫 rule 2.2 的限制)

or rule 2.2: 方法簽名同時滿足以下三點【總結:沒有額外的 self 型別引數的非泛型成員方法】

and rule 2.2.1 必須不包含任何泛型引數

and rule 2.2.2 第乙個引數必須為 self 型別,或者可以解引用為 self 型別

and rule 2.2.3 self 不能出現在除第乙個引數之外的地方,包括返回值

and rule 3: trait 中不能包含關聯常量(associated constant)

rule 2.1: "方法受 self: sized 約束" 實際上是告訴編譯器這個方法不會被動態呼叫。這樣編譯器就可以忽略對這個方法的檢查。sized trait 是讓整個 trait 沒法動態呼叫,對 方法的sized 只限定這個方法不行,這樣讓其他部分還是可以動態呼叫。相當於把約束範圍縮小了。

很多文章對都對這些規則有描述,但是常常把 rule3 「trait 中不能包含關聯常量」作為「物件安全的方法」,邏輯不對。這一條應該是乙個頂級規則。

下面的示例**對上面所有規則都做了演示,會導致編譯錯誤的**放到了 注釋中: 

// 可以轉成 trait 物件

trait good

fn use_good(_: &dyn good) -> (){}

//-------------------------------------------

trait badrule3

// 錯誤資訊:this trait cannot be made into an object. because it contains this associated `const`

//fn use_bad_rule3(_: &dyn badrule3) -> (){}

//-------------------------------------------

trait badrule1:sized

// 錯誤資訊: .because badrule1 requires `self: sized, this trait cannot be made into an object...

//fn use_bad_rule1(_: &dyn foogood) -> (){}

//-------------------------------------------

trait badrule221

// 錯誤資訊:this trait cannot be made into an object...,.because method `foo` has generic type parameters

//fn use_foo_bad_rule221(_: &dyn badrule221) -> (){}

//-------------------------------------------

trait badrule222

// 錯誤資訊:this trait cannot be made into an object...,.because associated function `foo` has no `self` parameter

//fn use_foo_bad_rule221(_: &dyn badrule222) -> (){}

//-------------------------------------------

trait badrule223

// 錯誤資訊:this trait cannot be made into an object...,.because method `foo` references the `self` type in its return type

//fn use_foo_bad_rule221(_: &dyn badrule223) -> (){}

//-------------------------------------------

// 可以轉換為 trait 物件,雖然使用泛型方法違反了 rule 2.2.1,但是 方法的 self:sized 滿足了 rule 2.1

trait goodrule21a

fn use_foo_good_rule21(_: &dyn goodrule21a) -> (){}

//-------------------------------------------

// 可以轉換為 trait 物件,雖然方法同時違反了 rule 2.2 包含的三條規則,但是 方法的 self:sized 滿足了 rule 2.1

// use_foo_good_rule21b 函式使用 goodrule21b 作為 trait 物件是可以編譯通過,但 foo2 方法受 rule 2.1 的約束是不能被動態呼叫的

trait goodrule21b

fn use_foo_good_rule21b(obj: &dyn goodrule21b) -> ()

//-------------------------------------------

fn main(){}

Eclipse 和 Myeclipse外掛程式安裝方法

eclipse外掛程式安裝方法 在工具欄開啟 help install new software 在彈出的視窗中open with 位址列輸入以下鏈結,enter鍵搜尋 svn外掛程式 codeguide外掛程式 decompiler外掛程式 activiti設計外掛程式 勾選搜尋到的外掛程式名,然...

TabStrip和MultiPage的安裝和使用

c inetpub wwwroot 下建立目錄 webctrl client 1 0,在 dos視窗裡執行 執行c program files ie web controls 目錄下readme.txt 檔案裡的 xcopy s i build runtime c inetpub wwwroot w...

常見安規和認證

ce 歐盟 安規 emc 強制 fcc 美國電磁相容 強制 pse 日本 強制和自願 etl美國安規 自願 gs 德國安規 自願 歐盟認可 emc 電磁相容指令 ul 美國安規 自願 vde 德國認證機構 安規 標誌認證是自願 kema 荷蘭認證機構 安規 標誌認證是自願 c tick 澳大利亞 e...