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

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

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

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

Q&A

解決済

1回答

1690閲覧

(Rust)publicメソッドの共通化について

退会済みユーザー

退会済みユーザー

総合スコア0

Rust

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

0グッド

0クリップ

投稿2019/06/14 09:42

編集2019/06/14 13:32

Rustで以下のようなコードがあるとき、 SidesSidesRatiois_valid メソッドをトレイト等を使って奇麗に共通化することは可能でしょうか。

rust

1pub mod geometry { 2 pub mod triangle { 3 // 各辺の長さ 4 pub struct Sides { 5 a: f64, 6 b: f64, 7 c: f64, 8 } 9 10 impl Sides { 11 pub fn new(a: f64, b: f64, c: f64) -> Sides { 12 Sides { a, b, c } 13 } 14 15 pub fn is_valid(self) -> bool { 16 return self.a > 0.0 17 && self.b > 0.0 18 && self.c > 0.0 19 && (self.a + self.b) > self.c 20 && (self.b + self.c) > self.a 21 && (self.c + self.a) > self.b; 22 } 23 } 24 25 // 各辺の比率 26 pub struct SidesRatio { 27 a: f32, 28 b: f32, 29 c: f32, 30 } 31 32 impl SidesRatio { 33 pub fn new(a: f32, b: f32, c: f32) -> SidesRatio { 34 SidesRatio { a, b, c } 35 } 36 37 // Sides::is_valid と完全に同一な内容 38 pub fn is_valid(self) -> bool { 39 return self.a > 0.0 40 && self.b > 0.0 41 && self.c > 0.0 42 && (self.a + self.b) > self.c 43 && (self.b + self.c) > self.a 44 && (self.c + self.a) > self.b; 45 } 46 } 47 48 #[cfg(test)] 49 mod tests { 50 use super::*; 51 52 #[test] 53 fn test () { 54 let sides = Sides::new(3.0, 4.0, 5.0); 55 assert_eq!(sides.is_valid(), true); 56 57 let sides_ratio = SidesRatio::new(3.0, 4.0, 5.0); 58 assert_eq!(sides_ratio.is_valid(), true); 59 } 60 } 61 } 62}

単純に以下のようにトレイト化すると、pubの記入で構文エラーとなり、selfもコンパイル時にSizeがわからないということでダメそうです。

pub trait IsValid { pub fn is_valid(self) -> bool { return self.a > 0.0 && self.b > 0.0 && self.c > 0.0 && (self.a + self.b) > self.c && (self.b + self.c) > self.a && (self.c + self.a) > self.b; } }

コードは以下に置いてあります。
Rust playground

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

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

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

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

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

guest

回答1

0

ベストアンサー

おそらく普通は以下の感じです:

rust

1use num_traits::Float; 2 3pub trait IsValid { 4 fn is_valid(&self) -> bool; 5} 6 7fn is_valid_default<T: Float>(a: T, b: T, c: T) -> bool { 8 a > 0.0 && b > 0.0 && c > 0.0 && (a + b) > c && (b + c) > a && (c + a) > b 9} 10 11// 各辺の長さ 12pub struct Sides { 13 a: f64, 14 b: f64, 15 c: f64, 16} 17 18impl Sides { 19 pub fn new(a: f64, b: f64, c: f64) -> Sides { 20 Sides { a, b, c } 21 } 22} 23 24impl IsValid for Sides { 25 fn is_valid(&self) -> bool { 26 is_valid_default(self.a, self.b, self.c) 27 } 28} 29 30// 各辺の比率 31pub struct SidesRatio { 32 a: f32, 33 b: f32, 34 c: f32, 35} 36 37impl SidesRatio { 38 pub fn new(a: f32, b: f32, c: f32) -> SidesRatio { 39 SidesRatio { a, b, c } 40 } 41} 42 43impl IsValid for SidesRatio { 44 fn is_valid(&self) -> bool { 45 is_valid_default(self.a, self.b, self.c) 46 } 47}

Sides::is_valid と完全に同一な内容

これは構文上同一ですが、変数の型がf64/f32で違っているので違う関数として解釈されます。一つの定義でこれらを同時に定義するにはジェネリクスを使用する必要があります。上のis_valid_default関数を見てみてください。Rustのジェネリクスでは課された制約にある機能しか使えないので、num_traits::Floatを使っています。

単純に以下のようにトレイト化すると、pubの記入で構文エラーとなり、selfもコンパイル時にSizeがわからないということでダメそうです。

traitについて幾つか誤解があるように見られますが、まず基本的にtraitは関数のインターフェースを書くもので、実装を書くものではありません。デフォルト実装という概念があるので実装を書くこともできますが、これはtraitの他の関数を使って書くものであくまでオプションです。

また、traitの関数はそのtraitをuseした段階で全て名前解決出来るようになるので関数の方にはpub宣言は必要ありません。

投稿2019/06/14 11:13

termoshtt

総合スコア136

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

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

退会済みユーザー

退会済みユーザー

2019/06/14 14:43 編集

コメントありがとうございます。 内容理解しました。traitの考え方についても親切に教えていただきありがとうございます。 Rustコードをそのまま試したところ `mismatched types` のエラーが出たため、 `num_traits::cast::FromPrimitive` を利用して解決出来ました。 https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2c65746133568fb62b42ff6b7bcef823 自分のやりたいことがこれで実現できそうです、ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問