質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

2回答

1020閲覧

Rust:traitのデフォルトメソッドの中で構造体のフィールドを参照することを前提に記述したい

kurokoSin

総合スコア133

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

1クリップ

投稿2022/12/30 09:18

前提

Rust でプログラムを組んでいます。
traitのデフォルトメソッドから構造体のフィールドの値を表示ようなメソッドを作成したいですが、記述方法がわかりません。
そもそもできないのでしょうか?
有識者の方、ご教示のほどよろしくお願いします。

ソース

具体的なサンプルソースです。

  • how_money メソッド(7行目)で、Apple.value をアテにしてreturn しています。

Rust

1struct Apple { 2 value: i32, 3} 4 5trait FruitTrait { 6 fn how_money(&self) -> i32 { 7 return self.value 8 } 9} 10 11impl FruitTrait for Apple{} 12 13fn main() { 14 let fruit = Apple{value: 300}; 15 println!("{}", fruit.how_money()); 16}

(上記の構造体は、Apple 一つですが、実際はOrange、Mango、Pine、、、、等多数になる予定です。)

発生している問題・エラーメッセージ

error[E0609]: no field `value` on type `&Self` --> src/main.rs:12:17 | 8 | trait FruitTrait { | ---------------- type parameter 'Self' declared here ... 12 | return self.value | ^^^^^ For more information about this error, try `rustc --explain E0609`. error: could not compile `playground` due to previous error

試したこと

以下の様にソースを修正したら、理想の形に近くはなりましたが、get_value が手間かかりますので、もう少し手間を省けないかと思っている次第です。

  • get_value() をtraitに追加。
  • impl の中でget_value() にvalueを返す用に指定。

あと、implの中で、how_money()を実行するためにget_value()を必ず実装しなければならないという制約もプログラムが複雑になってくると保守性が悪くなるのではと懸念しています。

rust

1struct Apple { 2 value: i32, 3} 4 5trait FruitTrait { 6 fn how_money(&self) -> i32 { 7 return self.get_value() 8 } 9 10 fn get_value(&self) -> i32; 11 12} 13 14impl FruitTrait for Apple { 15 fn get_value(&self) -> i32 { 16 return self.value 17 } 18} 19 20fn main() { 21 let fruit = Apple{value: 300}; 22 23 println!("{}", fruit.how_money()); 24}

補足情報(FW/ツールのバージョンなど)

環境:

$ rustc --version rustc 1.66.0 (69f9c33d7 2022-12-12)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

言語の機能としては出来ないと考えてよいと思います。 提案としては出ているものの進展している様子は見られません。

ゲッタを定義することでなんとかするのは一般的な方法だと思いますが確かに煩雑なのでそれをマクロで自動化する事例があるようです。

投稿2022/12/30 12:31

SaitoAtsushi

総合スコア5444

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kurokoSin

2022/12/30 15:02 編集

ありがとうございました。 リンクもありがとうございます! これで悶々と調べることなく、ゲッターで処理していけます。
guest

0

質問が閉まってるのに回答するのがマナー的にどうなのか分かりませんが、役に立てばと思い、追加情報を述べます。

構造体の持つフィールドをアテにした書き方をしたい場合は、そのフィールド自体を構造体にして、それにメソッドを紐づける方法もあります。質問文の改良方法とよく比較吟味して選択すべきですが、こちらの方法の方が後々楽になることもあります。個人的には、こちらの方法が、Rust の「継承よりコンポジション」の姿勢と合致していると思っています。

具体的には、店で売られている AppleTag (値札) を持ち、その Tagvalue が書かれていると考えます。how_money は店で売られていて (Saled)、 Tag が付いているものに対するメソッドなので、Tag に紐づけます。

Rust

1struct Tag {value: i32} 2 3struct Apple { 4 tag: Tag, 5} 6 7trait Saled { 8 fn how_money(&self) -> i32; 9} 10 11impl Saled for Tag { 12 fn how_money(&self) -> i32 { 13 self.value 14 } 15} 16 17fn main() { 18 let fruit = Apple{tag: Tag{value: 300}}; 19 println!("{}", fruit.tag.how_money()); 20}

このように、その概念が何を持っているのかに分解して考えた方が、Rust では自然に書けると、個人的には感じています。こんな方法もあるんだな程度に受け取ってください。

投稿2022/12/31 08:38

編集2022/12/31 08:39
mitnasdf

総合スコア9

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kurokoSin

2023/01/03 00:00

質問終了後にも関わらず、回答ありがとうございます! いただいた例を見ると、確かにこちらもいいですね。 参考にいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問