回答編集履歴

2

値をbox化するメソッドについて追記しました

2020/03/03 23:42

投稿

tatsuya6502
tatsuya6502

スコア2035

test CHANGED
@@ -111,3 +111,53 @@
111
111
 
112
112
 
113
113
  このように引数をとらないコンストラクタなら`Default`トレイトで実現できます。もしいくつかの共通の引数をとるようなコンストラクタが必要なら、`TraitB`とは別のトレイトを定義してみてください。
114
+
115
+
116
+
117
+ **追記**
118
+
119
+
120
+
121
+ 質問からは逸れますが `Box::new(StructB::default())`のような値をbox化するコードを頻繁に書く場合は、`StructB`にbox化するメソッド(またはトレイトメソッド)を実装すると少し書きやすくなりそうです。([こちら](https://keens.github.io/blog/2019/12/23/jisakulintru_rutocargo_fixderustnoko_doworifakutasuru/index.html#%E5%AE%9F%E8%B7%B5lint-fix)で紹介されているアイデアです)
122
+
123
+
124
+
125
+ ```rust
126
+
127
+ impl StructB {
128
+
129
+ fn boxed(self) -> Box<Self> {
130
+
131
+ Box::new(self)
132
+
133
+ }
134
+
135
+
136
+
137
+ fn boxed_new() -> Box<Self> {
138
+
139
+ Self::default().boxed()
140
+
141
+ }
142
+
143
+ }
144
+
145
+
146
+
147
+ fn main() {
148
+
149
+ let mut y: Box<dyn TraitB>;
150
+
151
+ // y = Box::new(StructB::default()) の代わりに以下のように書ける
152
+
153
+ y = StructB::default().boxed();
154
+
155
+ y = StructB::boxed_new();
156
+
157
+ }
158
+
159
+ ```
160
+
161
+
162
+
163
+ この例では`boxed(self)`と`boxed_new()`を何かのトレイトのメソッドにする理由は特になかったので、`Struct`のメソッドや関連関数として実装しました。もしトレイトのメソッドにする必要があれば、(`TraitB`とは別にトレイトを定義すれば)そうすることも可能です。

1

わかりやすさのために文章を修正しました(特に冒頭の部分)

2020/03/03 23:42

投稿

tatsuya6502
tatsuya6502

スコア2035

test CHANGED
@@ -1,22 +1,30 @@
1
- > `error[E0038]: the trait \`TraitB\` cannot be made into an object`
1
+ > 下記コードのStructAがOKで、StructBがNGである理由がなかなか理解できず…。
2
2
 
3
3
 
4
4
 
5
- Rustのエラーメッセージがよくわからないときは、まずエラーの説を読のがおすすめです。Webブラウザで [https://doc.rust-lang.org/error-index.html#E0038](https://doc.rust-lang.org/error-index.html#E0038) にアクセスするか、ターミナルから `rustc --explain 38` を実行します。(38のところを実際のエラー番号で置き換えます) 説明は英語ですが、最近は機械翻訳が高性能化してきているので、それらを活用すればなんとかなると思います。(例:[https://cn.bing.com/translator?from=&to=ja](https://cn.bing.com/translator?from=&to=ja))
5
+ こうときは、まずエラーの説を読んでみるのがおすすめです。
6
6
 
7
7
 
8
8
 
9
- E0038のところでは、トレイトオブジェクトにできないトレイトの条件が書かれています。その中で今回の`TraitB`が当てはまるのは以下の項目です。
9
+ > error[E0038]: the trait `TraitB` cannot be made into an object
10
10
 
11
11
 
12
12
 
13
- - トレトメソッド`Self`型引数たり、`Self`戻り値返したりす。(メソッドレシーバを示す`&self`などは問題ない
14
-
15
- - トレイトメソッドがメソッドレシーバ(`&self`, `&muf self`, `self`)を持たない
13
+ コンパ出力する多くエラーにはE0038のような番号がついています。この番号使エラーの詳細な解説を表示できます。Webブラウザで [https://doc.rust-lang.org/error-index.html#E0038](https://doc.rust-lang.org/error-index.html#E0038) を開くか、ターミナルから `rustc --explain 38` を実行します。英語による説明ですが、最近は機械翻訳性能向上が著しいので、それら活用すればなんとかなそうです。(例:[https://www.bing.com/translator?from=&to=ja](https://www.bing.com/translator?from=&to=ja)
16
14
 
17
15
 
18
16
 
19
- 理由を明すると長くなるので、ここは省略します。エラー説明を機械翻訳にけてみてください。また、いくつかの項目につては、[ここ](https://doc.rust-jp.rs/book/second-edition/ch17-02-trait-objects.html?highlight=trait,obje#a%E3%83%88%E3%83%AC%E3%82%A4%E3%83%88%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E3%81%AF%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E5%AE%89%E5%85%A8%E6%80%A7%E3%81%8C%E5%BF%85%E8%A6%81) で和訳されます。
17
+ E0038説でどういうトレイトがトレイトオブジェクトにきないのか、いくつかの条件が書かれてます。今回の`TraitB`が当るのは以下の条件です。
18
+
19
+
20
+
21
+ - `Self`型の引数をとったり、`Self`型の戻り値を返したりするトレイトメソッドがある。(メソッドレシーバを示す`&self`などは問題ない)
22
+
23
+ - メソッドレシーバ(`&self`, `&muf self`, `self`)を持たないトレイトメソッドがある
24
+
25
+
26
+
27
+ これらがなぜダメなのかの理由を説明しだすと長くなるので、ここでは省略します。エラーの解説を機械翻訳にかけてみてください。また、いくつかの項目については、[ここ](https://doc.rust-jp.rs/book/second-edition/ch17-02-trait-objects.html?highlight=trait,obje#a%E3%83%88%E3%83%AC%E3%82%A4%E3%83%88%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E3%81%AF%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E5%AE%89%E5%85%A8%E6%80%A7%E3%81%8C%E5%BF%85%E8%A6%81) で和訳されています。
20
28
 
21
29
 
22
30
 
@@ -99,3 +107,7 @@
99
107
  }
100
108
 
101
109
  ```
110
+
111
+
112
+
113
+ このように引数をとらないコンストラクタなら`Default`トレイトで実現できます。もしいくつかの共通の引数をとるようなコンストラクタが必要なら、`TraitB`とは別のトレイトを定義してみてください。