https://doc.rust-jp.rs/rust-by-example-ja/trait/disambiguating.html
に出てくるコードで最後の4行は
<Type as Trait>::function(receiver_if_method, next_arg, …);
のようなフルパス指定ししなくとも
let username = UsernameWidget::get(&form);
assert_eq!("rustacean".to_owned(), username);
let age = AgeWidget::get(&form);
assert_eq!(28, age);
と書いて、Traitを指定するだけでもコンパイルできます。関数の引数に(&form)、つまりFormのインスタンスを使っているからだと思いますが。
一方関連関数new()を追加した以下のコードだと、
trait UsernameWidget {
// Get the selected username out of this widget
fn get(&self) -> String;
fn new(name: String, age: u8) -> Self;
}
trait AgeWidget {
// Get the selected age out of this widget
fn get(&self) -> u8;
}
// A form with both a UsernameWidget and an AgeWidget
struct Form {
username: String,
age: u8,
}
impl UsernameWidget for Form {
fn get(&self) -> String {
self.username.clone()
}
fn new(str: String, age: u8) -> Self {
Form {
username: str,
age: age,
}
}
}
impl AgeWidget for Form {
fn get(&self) -> u8 {
self.age
}
}
fn main() {
// both UsernameWidget & AgeWidget are implemeneted to Form, you can use Form::new() instead of
// the fully-qualified path <form as="" usernamewidget="">::new(...)
let form = Form::new(String::from("John"), 30);
let username = UsernameWidget::get(&form);
assert_eq!("John".to_owned(), username);
let age = AgeWidget::get(&form); assert_eq!(30, age);
}
もし、
let form = Form::new(String::from("John"), 30);
を
let form = UsernameWidget::new(String::from("John"), 30);
とするとこれはコンパイルできない(use the fully-qualified path to the only available implementationのようなエラーが出る)、なぜなら関連関数(Associated function)だから構造体情報を持たないので対象の構造体を特定できないから。
しかしソースコードの最後のほうの行で、オリジナルソースのようにフルパスを指定してやれば、
let form = UsernameWidget::new(String::from("John"), 30);
でもコンパイルできる。これはコンパイラが構造体FormとトレイトUserWidgetの関連を他の行からの情報で知ることができるようになったからだろう。
構造体Formにアクセスするだけなら、Form::new(…..)を使うのが最もコンパクトで分かりやすいコードになりますが、これはimpl Trait for Structがあるから有効なコード。
フルパス記法については、
https://doc.rust-jp.rs/book-ja/ch19-03-advanced-traits.html
がオリジナルのテキストになります。
admin