Rust the book - 第10章

Posted by johtani on Thursday, May 28, 2020

目次

前回の記事はこちら。自分用のメモなので、読みにくいかもです。

第10章

ジェネリック、トレイト、ライフタイムです。 手強そう。

いきなり関数の切り出し方みたいな話が始まって面食らいました。

ジェネリックなデータ型

ジェネリックはJavaにもあるので、それほど理解に苦しむことはなかったです。 また、OptionやResultですでに経験済みでしたし。

ただ、impl<T> Point<T>{、このメソッド定義は少し最初は戸惑いました。 言われてみれば、なるほどなんですけど。

コンパイル時にコンパイラが単相化を行うことにより、必要最低限なコードを生成してくるというのは理にかなっているなぁと。

トレイト: 共通の振る舞いを定義する

出だしにもありますが、「インターフェイス」という機能に類似していると考えると割とすんなりと理解が進みました。 ただ、Javaだと、インターフェースはクラスとセットなため、トレイとの実装に関する記述方法は少し戸惑いが。

デフォルト実装との組み合わせはAbstractに似た処理になるなと考えながら読みすすめました。

「トレイト境界」という日本語には少し違和感を覚えましたが、線引をして、制限をかけるという理解でいいのかな?

実際には#[derive()]などで、トレイトを自分で実装する必要がないなどの、便利機能も用意されており、このあたりのコードの追い方がまだ少し慣れていないかもなぁと。便利なんですけど。。。

少しだけ気になったので、動作確認したのは次の実装です。

トレイトで宣言されている関数と構造体が独自に実装する関数の名前がかぶるとどうなるのかという実験です。 構造体独自のメソッドが優先される感じになりそう。

pub struct Tweet {
    pub username: String,
    pub content: String,
    pub reply: bool,
    pub retweet: bool,
}
pub trait Summary {
    fn summarize_author(&self) -> String;
    fn summarize(&self) -> String {
        // {}さんからもっと読む
        format!("(Read more from {}...)", self.summarize_author())
    }
}
impl Tweet {
    fn summarize_author(&self) -> String {
        format!("hoge {}", self.username)
    }
    fn to_string(&self) -> String {
        format!("fuga")
    }
}
impl Summary for Tweet {
    fn summarize_author(&self) -> String {
        format!("@{}", self.username)
    }
}
pub fn summary<T: Summary>(hoge: &T) {
    println!("{}", hoge.summarize_author());
}
pub fn main() {
    let tweet = Tweet {
        username: String::from("horse_ebooks"),
        content: String::from("of course, as you probably already know, people"),
        reply: false,
        retweet: false,
    };
    println!("{}", tweet.summarize_author());
    summary(&tweet);
    println!("{}", Summary::summarize_author(&tweet));
}

ライフタイムで参照を有効化する

言われてみればそうですが、プログラマが色々考えないとまぁ、行けないんですねという感想。

ただ、借用チェッカーが賢くやってくれるおかげで、全てにライフタイム注釈をつけなくて良くなっているというのがわかりました。 逆に言うと、なんとなくRustを書き始めてしまったので、それを知らずに書いたせいで、コンパイラに怒られてても「?」となっていたのかと。。。

疑問点がいくつかあって、

  • 通常はどんなライフタイム注釈をみんな書いてるんだろう?'aとかざっくりしすぎてる?
  • 1つのメソッド、関数にライフタイム注釈が大量に出てくるような書き方をした場合は設計がおかしいのでは?って考えたほうがいいのかも?
  • ジェネリックな型とライフタイム引数の順序を入れ替えてみても動くだろ?とおもって入れ替えてみたら怒られた。

あとは、構造体+ジェネリックが絡んできたら少しこんがらがってきそうっという感じです。 まぁ、これから先は実際に書いてみないことにはわからないんだろうなと。

まとめ

読みました。 実際にはプログラムを書きながら慣れていく感じだろうなぁと。 まだまだ、あれ?ジェネリックってどう書くんだっけ?とか、ライフタイム注釈どうやって付けて、使うときはどうすんだ?みたいになりながら、 出てくるサンプルを少し変えてみてはどうやって動くんだろうこの場合?みたいなことをやってました。 次は、11章、12章を少しだけ自習しつつ、13章に入る予定です(知り合いと一緒に読みすすめてる)。


comments powered by Disqus

See Also by Hugo


Related by prelims-cli