1.17.1. 一致性

一致性表示對於給定的型別和方法,只有一種正確的實作選擇。

孤兒規則的意思是,只要特徵或型別其中一方位於本地 crate,您就可以為該型別實作該特徵。 例如:

  • 您定義的本地型別可以實作 Debug 特徵
  • 您可以為 bool 實作您本地定義的特徵
  • 您無法為 bool 實作 Debug,因為雙方都不是本地的

孤兒規則有一些例外,我們將在下方討論。

1.17.2. 通用實作

通用實作(也稱為通用實作)是指 Rust 允許為滿足特徵約束的每一個型別提供預設實作。

其模板如下:

impl<T> MyTrait for T where T: ...

Enter fullscreen mode Exit fullscreen mode

這表示為所有實作某特徵的型別實作 MyTrait

例如:

impl<T: Display> ToString for T {}

Enter fullscreen mode Exit fullscreen mode

這表示為所有實作 Display 的型別實作 ToString

此範例尚未以模板形式撰寫。以模板形式呈現會是:

impl<T> ToString for T where T: Display {}

Enter fullscreen mode Exit fullscreen mode

請注意,只有定義該特徵的 crate 才允許使用通用實作。為既有特徵新增通用實作屬於破壞性變更。

1.17.3. 基礎型別

某些型別極為基礎,我們需要允許任何人為其實作特徵,即使這會違反孤兒規則。這些型別會被標記為 #[fundamental],目前包含 &T&mut TBox<T>Pin<P>

  • 額外提醒: Pin<P> 的主要用途是確保值不會被移動,也就是防止 std::mem::replacestd::mem::swapstd::mem::take 等操作改變該值的實體位址
  • 就孤兒規則而言,這些型別在進行孤兒規則檢查之前實際上會被抹除

注意:為基礎型別使用通用實作同樣視為破壞性變更。

1.17.4. 覆蓋實作

有時您需要為外部型別實作外部特徵,這稱為覆蓋實作。這使用了孤兒規則所建立的一個狹義豁免:允許在非常特定的情況下,為外部型別實作外部特徵。

注意:covered implementation 可指 Covered Implementation 或 Override Implementation。此處指的是 Covered Implementation。Override implementation 意指當結構體實作特徵並提供自己的方法時,可以覆寫預設實作。

此形式的模板如下:

impl<P1..=Pn> ForeignTrait<T1..=Tn> for T0

Enter fullscreen mode Exit fullscreen mode

  • P1..=PnT1..=T0 指多個參數

只有在符合以下所有條件時,才允許此形式:

  • T1..=Tn 中至少有一個是本地型別
  • 在第一個此類本地型別之前,不得出現 T(其中 TP1..=Pn 中的泛型型別之一)
  • 泛型型別參數 P 可以出現在 T0..Ti 中,只要它被某種中間型別包覆
    • T 作為另一型別的型別參數出現,例如 Vec<T>,則視為已包覆
    • T 單獨出現,或位於基礎型別如 &T 之後,則視為未包覆

簡單範例如下:

impl From<MyType> for Vec<i32>

Enter fullscreen mode Exit fullscreen mode

這為外部型別 Vec<i32> 實作了外部特徵 From<MyType>

以下是更複雜的範例。您可以使用上述規則來理解它們:

實作 是否有效?
impl<T> From<T> for MyType OK
impl<T> From<T> for MyType<T> OK
impl<T> From<MyType> for Vec<T> OK
impl<T> ForeignTrait<MyType, T> for Vec<T> OK
-------------------------------------------- ------------
impl<T> ForeignTrait for T Not OK
impl<T> From<T> for T Not OK
impl<T> From<Vec<T>> for T Not OK
impl<T> From<MyType<T>> for T Not OK
impl<T> From<T> for Vec<T> Not OK
impl<T> ForeignTrait<T, MyType> for Vec<T> Not OK

覆蓋實作是否為破壞性變更,取決於具體情況:

  • 為既有特徵新增實作,且至少包含一個符合上述條件的新本地型別,屬於非破壞性變更
  • 為既有特徵新增不符合上述條件的實作,屬於破壞性變更

注意:

  • impl<T> ForeignTrait<MyType, T> for Vec<T> 是有效的
  • impl<T> ForeignTrait<T, MyType> for Vec<T> 是無效的