1.17.1. 整合性
整合性とは、ある型とメソッドに対して、その型にそのメソッドを実装する正しい選択肢が 1 つだけ存在することを意味します。
孤児ルールとは、ローカルクレートのいずれか側がトレイトまたは型である場合、その型に対してそのトレイトを実装できることを意味します。 例:
- ローカルで定義した型は
Debugトレイトを実装できる - ローカルで定義したトレイトを
boolに対して実装できる Debugをboolに対して実装することはできない。どちらの側もローカルではないため
孤児ルールには例外があります。以下で説明します。
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
トレイトを定義したクレートだけがブランケット実装を使用できることに注意してください。既存のトレイトにブランケット実装を追加すると破壊的変更になります。
1.17.3. 基本型
一部の型は非常に基本的なため、孤児ルールに違反する場合でも、誰でもそれらにトレイトを実装できるようにする必要があります。これらの型は #[fundamental] とマークされており、現在 &T、&mut T、Box<T>、Pin<P> が含まれます。
- 補足:
Pin<P>の主な目的は、値が移動できないことを保証することです。つまり、std::mem::replace、std::mem::swap、std::mem::takeなどの操作が値の物理アドレスを変更するのを防ぐことです - 孤児ルールの目的では、これらの型は孤児ルールチェックが行われる前に実際に消去されます
注: 基本型にブランケット実装を使用することも破壊的変更とみなされます。
1.17.4. カバー実装
外部の型に対して外部のトレイトを実装する必要がある場合があります。これをカバー実装と呼びます。これは孤児ルールによって確立された狭い例外を使用します。外部の型に対して外部のトレイトを非常に特定のケースで実装することを許可します。
注: カバー実装は Covered Implementation または Override Implementation のいずれかを指すことがあります。ここでは Covered Implementation を指します。Override Implementation とは、構造体がトレイトを実装し、独自のメソッドを提供する場合に、デフォルト実装をオーバーライドできることを意味します。
この形式のテンプレートは次の通りです:
impl<P1..=Pn> ForeignTrait<T1..=Tn> for T0
Enter fullscreen mode Exit fullscreen mode
-
P1..=PnおよびT1..=T0はパラメータの数を指します
この形式は、次のすべての条件が満たされた場合にのみ許可されます:
T1..=Tnの少なくとも 1 つがローカル型である- そのようなローカル型の最初のものの前に
T(P1..=Pnのジェネリック型の 1 つ)が現れてはならない - ジェネリック型パラメータ
Pは、T0..Tiに中間型でラップされている限り現れることができるTがVec<T>などの別の型の型パラメータとして現れる場合、TはラップされているとみなされるTが単独で現れる場合、または&Tなどの基本型の背後に現れる場合、ラップされていない
簡単な例:
impl From<MyType> for Vec<i32>
Enter fullscreen mode Exit fullscreen mode
これは、外部の From<MyType> トレイトを外部の Vec<i32> 型に対して実装します。
より複雑な例をいくつか示します。上記のルールを使用して理解できます:
| 実装 | 有効? |
|---|---|
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 |
カバー実装が破壊的変更になるかどうかは、具体的な状況によって異なります:
- 既存のトレイトに新しい実装を追加し、上記の条件を満たす少なくとも 1 つの新しいローカル型を含む場合は、非破壊的変更
- 上記の条件を満たさない既存のトレイトの実装を追加するのは、破壊的変更
注:
-
impl<T> ForeignTrait<MyType, T> for Vec<T>は有効 -
impl<T> ForeignTrait<T, MyType> for Vec<T>は無効
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.