やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rustのオブジェクト指向

 struct, impl, pub, trait, トレイト境界where T: trait1, trait2、を用いて実現する。

成果物

オブジェクト=データ+振る舞い

pub struct AveragedCollection {
    list: Vec<i32>,
    average: f64,
}
impl AveragedCollection {
    pub fn new() -> AveragedCollection { AveragedCollection { list: vec![], average: 0.0 } }
    pub fn show(&self) { println!("ave: {}  {:?}", self.average, self.list); }
    pub fn add(&mut self, value: i32) {
        self.list.push(value);
        self.update_average();
    }
    pub fn remove(&mut self) -> Option<i32> {
        let result = self.list.pop();
        match result {
            Some(value) => {
                self.update_average();
                Some(value)
            },
            None => None,
        }
    }
    pub fn average(&self) -> f64 { self.average }
    fn update_average(&mut self) {
        let total: i32 = self.list.iter().sum();
        self.average = total as f64 / self.list.len() as f64;
    }
}
fn main() {
    let mut ac = AveragedCollection::new();
    ac.add(10);
    ac.show();
    ac.add(15);
    ac.show();
    ac.remove();
    ac.show();
}

カプセル化

 以下をpubせず非公開にすることで隠蔽している。

  • 構造体のフィールド
  • update_average()

継承

目的

 継承する目的は以下。

  1. コードの再利用
  2. 多相性を得るため(親の型と同じ箇所で子の型を使える)

 Rustにおいてはそれぞれ以下の方法で実現している。

  1. impl SomeTrait for SomeStruct {}
  2. トレイト境界: impl<T> SomeTrait<T> { fn some<T>(p: T) -> T where T: Clone, Debug {...} }

継承は落ち目

継承は、近年、多くのプログラミング言語において、プログラムの設計解決策としては軽んじられています。 というのも、しばしば必要以上にコードを共有してしまう危険性があるからです。

これらの理由により、継承ではなくトレイトオブジェクトを使用してRustは異なるアプローチを取っています。

 トレイトオブジェクトについては次回。

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで