Skip to content

4.30. Associated Types #72

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 86 additions & 47 deletions 1.6/ja/book/associated-types.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
% Associated Types

Associated types are a powerful part of Rust’s type system. They’re related to
the idea of a ‘type family’, in other words, grouping multiple types together. That
description is a bit abstract, so let’s dive right into an example. If you want
to write a `Graph` trait, you have two types to be generic over: the node type
and the edge type. So you might write a trait, `Graph<N, E>`, that looks like
this:
% 関連型
<!-- % Associated Types -->

<!-- Associated types are a powerful part of Rust’s type system. They’re related to -->
<!-- the idea of a ‘type family’, in other words, grouping multiple types together. That -->
<!-- description is a bit abstract, so let’s dive right into an example. If you want -->
<!-- to write a `Graph` trait, you have two types to be generic over: the node type -->
<!-- and the edge type. So you might write a trait, `Graph<N, E>`, that looks like -->
<!-- this: -->
関連型は、Rust型システムの強力な部分です。関連型は、「型族」という概念と関連が有り、
言い換えると、複数の型をグループ化するものです。
この説明はすこし抽象的なので、実際の例を見ていきましょう。
例えば、 `Graph` トレイトを定義したいとしましょう、このときジェネリックになる2つの型: 頂点の型、辺の型 が存在します。
そのため、以下のように `Graph<N, E>` と書きたくなるでしょう:

```rust
trait Graph<N, E> {
Expand All @@ -15,19 +21,24 @@ trait Graph<N, E> {
}
```

While this sort of works, it ends up being awkward. For example, any function
that wants to take a `Graph` as a parameter now _also_ needs to be generic over
the `N`ode and `E`dge types too:
<!-- While this sort of works, it ends up being awkward. For example, any function -->
<!-- that wants to take a `Graph` as a parameter now _also_ needs to be generic over -->
<!-- the `N`ode and `E`dge types too: -->
たしかに上のようなコードは動作しますが、この `Graph` の定義は少し扱いづらいです。
たとえば、任意の `Graph` を引数に取る関数は、 _同時に_ 頂点 `N` と辺 `E` についてもジェネリックとなることになります:

```rust,ignore
fn distance<N, E, G: Graph<N, E>>(graph: &G, start: &N, end: &N) -> u32 { ... }
```

Our distance calculation works regardless of our `Edge` type, so the `E` stuff in
this signature is just a distraction.
<!-- Our distance calculation works regardless of our `Edge` type, so the `E` stuff in -->
<!-- this signature is just a distraction. -->
この距離を計算する関数distanceは、辺の型に関わらず動作します、そのためシグネチャに含まれる `E` に関連する部分は邪魔でしかありません。

What we really want to say is that a certain `E`dge and `N`ode type come together
to form each kind of `Graph`. We can do that with associated types:
<!-- What we really want to say is that a certain `E`dge and `N`ode type come together -->
<!-- to form each kind of `Graph`. We can do that with associated types: -->
本当に表現したいことは、それぞれのグラフ( `Graph` )は辺( `E` )や頂点( `N` )で構成されているということです。
それは、以下のように関連型を用いて表現することができます:

```rust
trait Graph {
Expand All @@ -40,19 +51,25 @@ trait Graph {
}
```

Now, our clients can be abstract over a given `Graph`:
<!-- Now, our clients can be abstract over a given `Graph`: -->
このようにすると、`Graph` を使った関数は以下のように書くことができます:

```rust,ignore
fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> u32 { ... }
```

No need to deal with the `E`dge type here!
<!-- No need to deal with the `E`dge type here! -->
もう `E` について扱う必要はありません!


Let’s go over all this in more detail.
<!-- Let’s go over all this in more detail. -->
もっと詳しく見ていきましょう。

## Defining associated types
<!-- ## Defining associated types -->
## 関連型を定義する

Let’s build that `Graph` trait. Here’s the definition:
<!-- Let’s build that `Graph` trait. Here’s the definition: -->
早速、`Graph` トレイトを定義しましょう。以下がその定義です:

```rust
trait Graph {
Expand All @@ -64,12 +81,15 @@ trait Graph {
}
```

Simple enough. Associated types use the `type` keyword, and go inside the body
of the trait, with the functions.
<!-- Simple enough. Associated types use the `type` keyword, and go inside the body -->
<!-- of the trait, with the functions. -->
非常にシンプルですね。関連型には `type` キーワードを使い、そしてトレイトの本体や関数で利用します。

These `type` declarations can have all the same thing as functions do. For example,
if we wanted our `N` type to implement `Display`, so we can print the nodes out,
we could do this:
<!-- These `type` declarations can have all the same thing as functions do. For example, -->
<!-- if we wanted our `N` type to implement `Display`, so we can print the nodes out, -->
<!-- we could do this: -->
これらの `type` 宣言は、関数で利用できるものと同じものが全て利用できます。
たとえば、 `N` 型が `Display` を実装していて欲しい時、つまり私達が頂点を出力したい時、以下のようにして指定することができます:

```rust
use std::fmt;
Expand All @@ -83,10 +103,13 @@ trait Graph {
}
```

## Implementing associated types
<!-- ## Implementing associated types -->
## 関連型を実装する

Just like any trait, traits that use associated types use the `impl` keyword to
provide implementations. Here’s a simple implementation of Graph:
<!-- Just like any trait, traits that use associated types use the `impl` keyword to -->
<!-- provide implementations. Here’s a simple implementation of Graph: -->
通常のトレイトと同様に、関連型を使っているトレイトは実装するために `impl` を利用します。
以下は、シンプルなGraphの実装例です:

```rust
# trait Graph {
Expand Down Expand Up @@ -115,23 +138,34 @@ impl Graph for MyGraph {
}
```

This silly implementation always returns `true` and an empty `Vec<Edge>`, but it
gives you an idea of how to implement this kind of thing. We first need three
`struct`s, one for the graph, one for the node, and one for the edge. If it made
more sense to use a different type, that would work as well, we’re just going to
use `struct`s for all three here.
<!-- This silly implementation always returns `true` and an empty `Vec<Edge>`, but it -->
<!-- gives you an idea of how to implement this kind of thing. We first need three -->
<!-- `struct`s, one for the graph, one for the node, and one for the edge. If it made -->
<!-- more sense to use a different type, that would work as well, we’re just going to -->
<!-- use `struct`s for all three here. -->
この奇妙な実装は、つねに `true` と空の `Vec<Edge>` を返しますますが、どのように定義したら良いかのアイデアをくれます。
まず、はじめに3つの `struct` が必要です、ひとつはグラフのため、そしてひとつは頂点のため、そしてもうひとつは辺のため。
もし異なる型を利用することが適切ならば、そのようにすると良いでしょう、今回はこの3つの `struct` を用います。


Next is the `impl` line, which is just like implementing any other trait.
<!-- Next is the `impl` line, which is just like implementing any other trait. -->
次は `impl` の行です、これは他のトレイトを実装するときと同様です。

From here, we use `=` to define our associated types. The name the trait uses
goes on the left of the `=`, and the concrete type we’re `impl`ementing this
for goes on the right. Finally, we use the concrete types in our function
declarations.
<!-- From here, we use `=` to define our associated types. The name the trait uses -->
<!-- goes on the left of the `=`, and the concrete type we’re `impl`ementing this -->
<!-- for goes on the right. Finally, we use the concrete types in our function -->
<!-- declarations. -->
そして、`=` を関連型を定義するために利用します。
トレイトが利用する名前は `=` の左側にある名前で、実装に用いる具体的な型は右側にあるものになります。
最後に、具体的な型を関数の宣言に利用します。

## Trait objects with associated types
<!-- ## Trait objects with associated types -->
## 関連型を伴うトレイト

There’s one more bit of syntax we should talk about: trait objects. If you
try to create a trait object from an associated type, like this:
<!-- There’s one more bit of syntax we should talk about: trait objects. If you -->
<!-- try to create a trait object from an associated type, like this: -->
すこし触れておきたい構文: トレイトオブジェクト が有ります。
もし、トレイトオブジェクトを以下のように関連型から作成しようとした場合:

```rust,ignore
# trait Graph {
Expand All @@ -157,7 +191,8 @@ let graph = MyGraph;
let obj = Box::new(graph) as Box<Graph>;
```

You’ll get two errors:
<!-- You’ll get two errors: -->
以下の様なエラーが発生します:

```text
error: the value of the associated type `E` (from the trait `main::Graph`) must
Expand All @@ -170,8 +205,10 @@ let obj = Box::new(graph) as Box<Graph>;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```

We can’t create a trait object like this, because we don’t know the associated
types. Instead, we can write this:
<!-- We can’t create a trait object like this, because we don’t know the associated -->
<!-- types. Instead, we can write this: -->
上のようにしてトレイトオブジェクトを作ることはできません、なぜなら関連型について知らないからです
代わりに以下のように書くことができます:

```rust
# trait Graph {
Expand All @@ -197,6 +234,8 @@ let graph = MyGraph;
let obj = Box::new(graph) as Box<Graph<N=Node, E=Edge>>;
```

The `N=Node` syntax allows us to provide a concrete type, `Node`, for the `N`
type parameter. Same with `E=Edge`. If we didn’t provide this constraint, we
couldn’t be sure which `impl` to match this trait object to.
<!-- The `N=Node` syntax allows us to provide a concrete type, `Node`, for the `N` -->
<!-- type parameter. Same with `E=Edge`. If we didn’t provide this constraint, we -->
<!-- couldn’t be sure which `impl` to match this trait object to. -->
`N=Node` 構文を用いて型パラメータ `N` にたいして具体的な型 `Node` を指定することができます、`E=Edge` についても同様です。
もしこの制約を指定しなかった場合、このトレイトオブジェクトに対してどの `impl` がマッチするのか定まりません。
1 change: 1 addition & 0 deletions TranslationTable.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
| tick | クオート
| trait | トレイト
| type inference | 型推論
| type family | 型族
| Universal Function Call Syntax | 共通の関数呼び出し構文
| unsigned | 符号無し
| unsized type | サイズ不定型
Expand Down