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