Skip to main content

能力:丟棄 (Abilities: Drop)

在大多數程式語言中,不對某個值進行任何處理並不是問題:未使用的變數至多可能觸發警告,並會在其離開作用域的瞬間被遺忘。如同我們在 結構 (Struct) 章節所見,在 Move 中預設情況恰好相反:結構值必須被 使用——儲存在某處、傳遞出去,或解構——而靜默丟棄值的程式無法編譯。

drop 能力——四種能力中最簡單的一種——可讓你不遵守此規則。具有 drop 的結構可被 忽略 或 丟棄:繫結至永不讀取的變數、以 _ 萬用字元忽略,或在其作用域結束時直接留下。換言之,drop 讓 Move 型別的行為方式如同大多數其他語言中的值:

module book::drop_ability;

/// This struct has the `drop` ability.
public struct IgnoreMe has drop {
a: u8,
b: u8,
}

/// This struct does not have the `drop` ability.
public struct NoDrop {}

#[test]
// Create an instance of the `IgnoreMe` struct and ignore it.
// Even though we constructed the instance, we don't need to unpack it.
fun test_ignore() {
let no_drop = NoDrop {};
let _ = IgnoreMe { a: 1, b: 2 }; // no need to unpack

// The value must be unpacked for the code to compile.
let NoDrop {} = no_drop; // OK
}

在上述範例中,IgnoreMe 執行個體被指定給 _,且從未解構——程式碼可以編譯,因為 IgnoreMe 具有 drop 能力。NoDrop 執行個體無法以這種方式處理:僅有兩種選擇,保留它或解構它,而測試會在最後一行將其解構。

drop 能力僅允許 丟棄 值。它不允許複製或儲存值——這些行為分別由獨立的 copy 與 store 能力管理。

何時使用 drop (When to Use drop)​

一項實用原則:drop 適用於表示 資料 的型別;缺少它則可保護表示 資產 或 義務 的型別。

設定值、中繼資料、計算的中間結果——這些都不值得保護,強迫程式設計者明確銷毀每一個值只會徒增儀式感。為這類型別賦予 drop 能力可讓程式碼保持簡潔。集合型別是很好的範例:由於 vector 具有 drop(當其內容也具有時),不再需要的數字向量可以直接被遺忘。

另一方面,缺少 drop 是 Move 型別系統的定義性特徵之一。硬幣、票券、收據、償還義務——這類值絕不可靜默消失,而不具備 drop 的型別可在編譯器層級提供此保證:持有該值的人會被 強制 對其進行有意義的處理。由編譯器強制處理值,是熱馬鈴薯模式 (Hot Potato pattern) 的基礎;該模式已在前一節 (previous section) 提及,而我們會在所有權與作用域 (Ownership and Scope) 章節中探討值如何在作用域之間移動的完整規則。

僅具有 drop 一種能力的結構稱為 Witness。我們會在見證與抽象實作 (Witness and Abstract Implementation) 章節中說明 Witness 的概念。

具有 drop 能力的型別 (Types with the drop Ability)​

Move 中所有原生型別都具有 drop 能力。包括:

標準函式庫中定義的所有型別也都具有 drop 能力。包括:

請注意清單中的模式:如 vector 或 Option 的容器型別,只有在其內容可被丟棄時才能被丟棄。若向量中的元素受到保護而不可丟棄,持有它們的向量也會受到保護——否則丟棄容器將成為丟棄其內容的漏洞。

延伸閱讀 (Further Reading)​