在Rust中执行以下操作的规范方法是什么?
let s: Shape;
if something {
s = Circle::new();
} else {
s = Square::new();
}
对我来说最明显的方式是:
use std::env;
trait Shape {
fn area(&self) -> f32;
}
struct Circle {
rad: f32,
}
impl Circle {
pub fn new() -> Circle {
Circle {
rad: 5.0,
}
}
}
impl Shape for Circle {
fn area(&self) -> f32 {
self.rad * self.rad * 3.14159
}
}
struct Square {
len: f32,
}
impl Square {
pub fn new() -> Square {
Square {
len: 5.0,
}
}
}
impl Shape for Square {
fn area(&self) -> f32 {
self.len * self.len
}
}
fn main() {
let args: Vec<String> = env::args().collect();
let s: Shape;
if args.len() > 1 {
s = Circle::new();
} else {
s = Square::new();
}
println!("Area: {}", s.area());
}
结果:
error[E0277]: the trait bound `Shape: std::marker::Sized` is not satisfied
--> src/main.rs:46:9
|
46 | let s: Shape;
| ^ `Shape` does not have a constant size known at compile-time
|
一般来说,Circle和Square可能确实有不同的尺寸,所以我们真的不能知道什么尺寸的&#39; s&#39;将在编译时。
这个问题Polymorphism in Rust似乎表明你需要编写一个包装器结构(在这个例子中称为ShapeStruct),它采用泛型,并且你可以在这里分解出trait实现的每个函数:
struct ShapeStruct<T> {
shape: T,
}
impl<T: Shape> ShapeStruct<T> {
fn area(&self) -> f32 {
self.shape.area()
}
}
但是这会产生很多样板 - 特征声明的每个功能都需要突破,例如&#39; area&#39;在上面突破了。有没有更好的办法?