Drop

https://doc.rust-lang.org/book/drop.html

Dropというtraitsについて。 変数が消える時に、何かやらせたい時に使う。デストラクタってやつですね。

struct HasDrop;

impl Drop for HasDrop {
    fn drop(&mut self) {
        println!("Dropping!");
    }
}

struct Firework {
    strength: i32,
}

impl Drop for Firework {
    fn drop(&mut self) {
        println!("BOOM times {}!!!", self.strength);
    }
}

fn main() {
    println!("one");
    {
        let x = HasDrop;
        println!("two");
    }
    println!("three");

    let firecracker = Firework { strength: 1 };
    let tnt = Firework { strength: 100 };
}
$ cargo run # warning等は省略
one
two
Dropping!
three
BOOM times 100!!!
BOOM times 1!!!

Traits

https://doc.rust-lang.org/book/traits.html

JavaInterfaceC++のvirtual functionに相当する機能をRustでは、Trait( 特性、特徴)と呼ぶ。

trait HasArea {
    fn area(&self) -> f64;
    fn is_larger(&self, &Self) -> bool;
}

fn print_area<T: HasArea>(shape: T) {
    println!("This shape has an area of {}", shape.area());
}

struct Circle {
    x: f64,
    y: f64,
    radius: f64,
}

impl HasArea for Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * (self.radius * self.radius)
    }
}

struct Square {
    x: f64,
    y: f64,
    side: f64,
}

impl HasArea for Square {
    fn area(&self) -> f64 {
        self.side * self.side
    }
}

fn main() {
    let c = Circle {
        x: 0.0f64,
        y: 0.0f64,
        radius: 1.0f64,
    };

    let s = Square {
        x: 0.0f64,
        y: 0.0f64,
        side: 1.0f64,
    };

    print_area(c);
    print_area(s);
}

Generics

https://doc.rust-lang.org/book/generics.html

T(型)を指定する事で、色々と使えるテンプレート機能。 <T>を明示的に指定せずとも、使えるのがスゴい。

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn swap(&mut self) {
        std::mem::swap(&mut self.x, &mut self.y);
    }
}

fn main() {
    let mut int_point = Point { x: 3, y: 2 };
    let mut float_point = Point { x: 0.3, y: 0.2 };
    // let mut error_point = Point { x: 3, y: 0.2 }; // xが整数なのに、yが小数で型が違うため、エラーになる。

    println!("({}, {})", int_point.x, int_point.y);
    int_point.swap();
    println!("({}, {})", int_point.x, int_point.y);

    println!("({}, {})", float_point.x, float_point.y);
    float_point.swap();
    println!("({}, {})", float_point.x, float_point.y);
}

Strings

https://doc.rust-lang.org/book/strings.html

    let s = "foo
    bar";
    let t = "foo\n    bar";

stが同じ意味になるのが面白い。

    let hachiko = "忠犬ハチ公";
    for b in hachiko.as_bytes() {
        print!("{}, ", b);
    }
    println!("");
    for c in hachiko.chars() {
        print!("{}, ", c);
    }
    println!("");
229, 191, 160, 231, 138, 172, 227, 131, 143, 227, 131, 129, 229, 133, 172,
忠, 犬, ハ, チ, 公,

バイト表記と文字表記が可能。UTF-8の文字列サンプルとしてハチ公が選ばれたのはなぜなんだろう?