Namaran

Code daily. Without assist.

2026-08-25

shape_dyn.rs

trait Shape {
    fn area(&self) -> f64;

    fn describe(&self) -> String {
        format!("area = {:.1}", self.area())
    }

    fn scaled(&self, factor: f64) -> Self
    where
        Self: Sized;
}

struct Square {
    side: f64,
}

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

    fn scaled(&self, factor: f64) -> Self {
        Square { side: self.side * factor }
    }
}

fn main() {
    let big = Square { side: 3.0 }.scaled(2.0);
    let shapes: Vec<Box<dyn Shape>> = vec![Box::new(big)];
    for s in &shapes {
        println!("{}", s.describe());
    }
}

これは何を出力するでしょうか?

Answer

area = 36.0(その後に改行)。scaledSelfを値で返すので、そのままではdyn Shapeにできません(オブジェクト安全ではありません)。where Self: Sizedを付けると、その1メソッドだけを仮想関数テーブルから除外でき、トレイト自体はdyn Shapeのままにできます。実際コード中でもscaleddyn Shape経由ではなく具体型Squareに対して直接呼んでいます。side: 3.0factor: 2.0倍したSquare { side: 6.0 }Box<dyn Shape>に入れ、動的ディスパッチでdescribe(デフォルト実装)を呼ぶと、内部でself.area()Squareの実装に仮想的に解決され36.0になります。