diff --git a/src/ch15-02-deref.md b/src/ch15-02-deref.md index 9392d0a9b..c6bc6b1d9 100644 --- a/src/ch15-02-deref.md +++ b/src/ch15-02-deref.md @@ -177,8 +177,8 @@ references by default. Then we’ll look at how to add the ability to use the dereference operator. --> -標準ライブラリが提供している`Box`型に似たスマートポインタを構築して、スマートポインタは既定で -参照に比べてどう異なって振る舞うのか経験しましょう。それから、参照外し演算子を使う能力を追加する方法に目を向けましょう。 +標準ライブラリが提供している`Box`型に似たスマートポインタを作りましょう。そうすれば、スマートポインタがそのままだと +参照と同じ様には振る舞わないことがわかります。それから、どうすれば参照外し演算子を使えるようになるのか見てみましょう。 -`Box`型は究極的に1要素のタプル構造体として定義されているので、リスト15-8は、同じように`MyBox`型を定義しています。 -また、`Box`に定義された`new`関数と合致する`new`関数も定義しています。 +`Box`型は突き詰めると(訳註:データがヒープに置かれることを無視すると)1要素のタプル構造体のような定義になります。なのでリスト15-8ではそのように`MyBox`型を定義しています。 +また、`Box`に定義された`new`関数に対応する`new`関数も定義しています。 -`MyBox`という構造体を定義し、ジェネリック引数の`T`を宣言しています。自分の型にどんな型の値も保持させたいからです。 -`MyBox`型は、型`T`を1要素持つタプル構造体です。`MyBox::new`関数は型`T`の引数を1つ取り、 -渡した値を保持する`MyBox`インスタンスを返します。 +`MyBox`という構造体を定義し、ジェネリック引数の`T`を宣言しています。この型にどんな型の値も持たせたいからです。 +`MyBox`型は型`T`の要素を1つ持つタプル構造体です。`MyBox::new`関数は型`T`の引数を1つ取り、 +渡した値を持つ`MyBox`のインスタンスを返します。 -試しにリスト15-7の`main`関数をリスト15-8に追加し、`Box`の代わりに定義した`MyBox`型を使うよう変更してみてください。 +試しにリスト15-7の`main`関数をリスト15-8に追加し、定義した`MyBox`型を`Box`の代わりに使うよう変更してみてください。 コンパイラは`MyBox`を参照外しする方法がわからないので、リスト15-9のコードはコンパイルできません。 -こちらが結果として出るコンパイルエラーです: +こちらが結果として出るコンパイルエラーです。 ```text error[E0614]: type `MyBox<{integer}>` cannot be dereferenced @@ -276,7 +276,7 @@ ability on our type. To enable dereferencing with the `*` operator, we implement the `Deref` trait. --> -`MyBox`に参照外しの能力を実装していないので、参照外しできません。`*`演算子で参照外しできるようにするには、 +`MyBox`の参照を外すことはできません。そのための実装を与えていないからです。`*`演算子で参照外しできるようにするには、 `Deref`トレイトを実装します。 -第10章で議論したように、トレイトを実装するには、トレイトの必須メソッドに実装を提供する必要があります。 -`Deref`トレイトは標準ライブラリで提供されていますが、`self`を借用し、 -内部のデータへの参照を返す`deref`という1つのメソッドを実装する必要があります。リスト15-10には、 -`MyBox`の定義に追記する`Deref`の実装が含まれています: +第10章で議論したように、トレイトを実装するにはトレイトの必須メソッドに実装を与える必要があります。 +`Deref`トレイトは標準ライブラリで提供されており、`deref`という1つのメソッドの実装を要求します。`deref`は`self`を借用し、 +内部のデータへの参照を返すメソッドです。 +リスト15-10には、`MyBox`の定義に付け足す`Deref`の実装が含まれています。 -`type Target = T;`という記法は、`Deref`トレイトが使用する関連型を定義しています。関連型は、 -ジェネリック引数を宣言する少しだけ異なる方法ですが、今は気にする必要はありません; 第19章でより詳しく講義します。 +`type Target = T;`という記法は、`Deref`トレイトが使用する関連型を定義しています。関連型はまた少し違ったやり方でジェネリック引数を宣言するためのものですが、今は気にする必要はありません。第19章でより詳しく扱います。 -`deref`メソッドの本体を`&self.0`で埋めているので、`deref`は`*`演算子でアクセスしたい値への参照を返します。 +`deref`メソッドの本体は`&self.0`だけなので、`deref`が返すのは私達が`*`演算子でアクセスしたい値への参照なわけです。 リスト15-9の`MyBox`に`*`を呼び出す`main`関数はこれでコンパイルでき、アサートも通ります! -`Deref`がなければ、コンパイラは`&`参照しか参照外しできなくなります。`deref`メソッドによりコンパイラは、 -`Deref`を実装するあらゆる型の値を取り、`deref`メソッドを呼び出して参照外しの仕方を知っている`&`参照を得る能力を獲得するのです。 +`Deref`トレイトがないと、コンパイラは`&`参照しか参照外しできません。 +`deref`メソッドのおかげで、コンパイラは`Deref`を実装している型の値を取り、`deref`メソッドを呼ぶことで、参照外しが可能な`&`参照を得られるようになります。 -リスト15-9に`*y`を入力した時、水面下でコンパイラは、実際にはこのようなコードを走らせていました: +リスト15-9に`*y`を入力した時、水面下でRustは実際にはこのようなコードを走らせていました。 ```rust,ignore *(y.deref()) ``` - -コンパイラは、`*`演算子を`deref`メソッド、それから何の変哲もない参照外しの呼び出しに置き換えるので、 -`deref`メソッドを呼び出す必要があるかどうかを考える必要はないわけです。このRustの機能により、 -普通の参照か`Deref`を実装した型であるかどうかに関わらず、等しく機能するコードを書かせてくれます。 +Rustが`*`演算子を`deref`メソッドの呼び出しと普通の参照外しへと置き換えてくれるので、 +私達は`deref`メソッドを呼び出す必要があるかどうかを考えなくて済むわけです。このRustの機能により、 +普通の参照か`Deref`を実装した型であるかどうかに関わらず、等しく機能するコードを書くことができます。 -`deref`メソッドが値への参照を返し、`*(y.deref())`のかっこの外の何の変哲もない参照外しがそれでも必要な理由は、 -所有権システムです。`deref`メソッドが値への参照ではなく、値を直接返したら、値は`self`から外にムーブされてしまいます。 -今回の場合や、参照外し演算子を使用する多くの場合には`MyBox`の中の値の所有権を奪いたくはありません。 +`deref`メソッドが値への参照を返し、`*(y.deref())`のかっこの外にある普通の参照外しがそれでも必要になるのは、 +所有権システムがあるからです。`deref`メソッドが値への参照ではなく値を直接返したら、値は`self`から外にムーブされてしまいます。 +今回もそうですが、参照外し演算子を使用するときはほとんどの場合、`MyBox`の中の値の所有権を奪いたくはありません。 - -`*`演算子は、コードで`*`を打つたびに、ただ1回、`deref`メソッドの呼び出し、そして`*`演算子の呼び出しに置き換えられることに注意してください。 -`*`演算子の置き換えは、無限に繰り返されないので、型`i32`に行き着き、リスト15-9で`assert_eq!`の`5`と合致します。 +`*`演算子が`deref`メソッドの呼び出しと`*`演算子の呼び出しに置き換えられるのは、コード内で`*`を打つ毎にただ1回だけ、という点に注意して下さい。 +`*`演算子の置き換えは無限に繰り返されないので、型`i32`のデータに行き着きます。これはリスト15-9で`assert_eq!`の`5`と合致します。