ぺんぎんメモ

プログラミングのメモです。たまに私生活のことや鬱っぽいことを書きます。

非直感的なRustの仕様

ターミナルで cargo new my-crate を実行して my-crate プロジェクトを作成後、src/main.rs と src/lib.rs をそれぞれ次のように変更してコンパイルするとエラーが発生します。

// src/main.rs
extern crate my_crate;

use my_crate::MyStruct;

fn main() {
    MyStruct.my_method();
}
// src/lib.rs
pub struct MyStruct;

pub trait MyTrait {
    fn my_method(&self) {
        println!("hello, world");
    }
}

impl MyTrait for MyStruct {}

エラーは「my_crate::MyStructmy_method という名前のメソッドが存在しない」という内容です。

この問題を解決するためには、使いたいメソッドを含むトレイトを use する必要があります。つまり、main.rs に use my_crate::MyTrait; を追加します。これで my_method が使えるようになります。

// src/main.rs
extern crate my_crate;

use my_crate::MyTrait;
use my_crate::MyStruct;

fn main() {
    MyStruct.my_method();
}

この挙動が今の僕には不思議です。なぜかというと、構造体がトレイトに属した時点で、そのトレイト内のメソッドもすべて使えるようになるのが自然に思えるからです(「構造体がトレイトに属する」とは impl MyTrait for MyStruct {} のことです)。

ファイルの内容を読み取り String に格納するメソッド read_to_string がまさにこれで、read_to_string を使うためには std::io::Read; を use する必要があります。

use std::fs::File;
use std::io::Read;

fn main() {
    let mut f = File::open("input.txt").unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s).ok();
}

「メソッドはオブジェクトにくっついているもの」という認識だったので、Rust のこの仕様には少し戸惑いました。