やっつけな日常(33) Rustに入ればRustに従え、self、Self、&self

Joseph Halfmoon

ちんたら勉強しているRust言語です。Exampleのソースコードを拝見していて気になるのが、selfだったり、Selfだったりする self です。Pythonのselfのような「慣用語」的お約束ではなく keyword みたいです。大文字になったり、小文字だったり、&がついたり、::がついたり一体全体これは何?

Rustのソースを読んでいると時々目につく self ですが、最初は「そんなもん」で通り過ぎていましたが、だんだんそうもいってられなくなりました。以下のような形で度々登場してくるためです。

    • self
    • &self
    • self::
    • -> Self

それにちゃんと self と書かないとエラーになります。Pythonのself のような慣用句的お約束ではありません。

今回は、何時もお世話になっております、「Rust By Example 日本語版」様の以下のページを参照させていただいております。

superとself

FromおよびInto

トレイト

そんな理解でいいのか?

self:: として現れてくる self は、「同じモジュールスコープ」を明示的に示すために使われる、と。いくつかのスコープに同名の関数があるような場合に、明示的に自階層を指し示すために使えるようです。

Self として大文字で現れてくる Self は、「自オブジェクトの型」を示すためのものみたいです。トレイトであったり、ジェネリクスであったり Rust には「任意の型になりうる」データがありえ、そいつらのその時の型を指し示したいときに大文字の Self が使えると。戻り値の型として登場すれば -> Self となると。

小文字の self はメソッドが作用するオブジェクト自身を指すみたいですが、&self とか、*selfとかにもなりうるのがちょっとヤバイです。

いい加減な理解で書いたソース

実験のため、上記のいい加減な理解で書いたソースが以下に。trait とか impl とか慣れないことしています。大丈夫か?

struct Abc {
    dat1: i32,
}

trait Xyz {
    fn new(dat1: i32) -> Self;
    fn d1(&self) -> i32;
}

impl Xyz for Abc {
    fn new(dat1: i32) -> Abc {
        Abc { dat1: dat1 }
    }

    fn d1(&self) -> i32 {
        self.dat1
    }
}

fn d1(arg: &Abc) {
    println!("fn d1 = {}", arg.dat1);
}

fn main() {
    println!("Self, self");
    let test: Abc = Xyz::new(34);
    d1(&test);
    println!("test.d1={}", test.d1());
}
実行結果

上記を実行してみたところが以下に。

Result

一応、大文字の Self も 小文字の self も意図通りに動いてくれているみたいだけれども何だかな~、直ぐに間違えちゃいそうだな~。

やっつけな日常(32) Rustに入ればRustに従え、文字列操作、おっかなびっくり その1 へ戻る

やっつけな日常(34) Rustに入ればRustに従え、self.0って何?構造体とトレイト へ進む