Cha*_*Liu 6 polymorphism enums rust
使用enum Axes来限制Coordinate和Quaternion:
#[derive(Clone)]
pub enum Axes {
Coordinate {x: f64, y: f64, z: f64, reserve: Vec<f64>,},
Quaternion {x: f64, y: f64, z: f64},
}
impl Axes {
pub fn shift(&mut self, Sample: &Axes) -> () {
let Dup: Axes = self.clone();
match Dup {
Axes::Coordinate {x, y, z, reserve} => {
match &Sample {
Axes::Coordinate {x, y, z, reserve} => {
*self = Axes::Coordinate {x: *x, y: *y, z: *z, reserve: reserve.to_vec()};
}
_ => panic!(),
}
}
Axes::Quaternion {x, y, z} => {
match &Sample {
Axes::Quaternion {x, y, z} => {
*self = Axes::Quaternion {x: *x, y: *y, z: *z};
}
_ => panic!(),
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用特征Axes链接struct Coordinate和Quaternion:
pub trait Axes {
fn shift(&mut self, Sample: &Axes) -> ();
fn fold(&mut self, Sample: &Axes) -> ();
}
pub struct Coordinate {
pub x: f64,
pub y: f64,
pub z: f64,
pub reserve: Vec<f64>,
}
pub struct Quaternion {
pub x: f64,
pub y: f64,
pub z: f64,
}
impl Axes for Coordinate {
fn shift(&mut self, Sample: &Axes) -> () { }
fn fold(&mut self, Sample: &Axes) -> () { }
}
impl Axes for Quaternion {
fn shift(&mut self, Sample: &Axes) -> () { }
fn fold(&mut self, Sample: &Axes) -> () { }
}
Run Code Online (Sandbox Code Playgroud)
struct在这种情况下,具有trait的特征是否更容易获得和更有效?我对在什么情况下使用哪个感到困惑。
在根据情况使用特征和枚举之间的最大区别之一是它们的可扩展性。如果创建Axes枚举,则这两个选项将硬编码到类型中。如果要添加某种轴的第三种形式,则必须修改类型本身,这可能会涉及对带有用途的代码进行大量修改Axes(例如,Axes可能需要更改在a上匹配的任何位置)。另一方面,如果要制作Axes特征,则可以通过定义新类型并编写适当的实现方式来添加其他类型的轴,而无需完全修改现有代码。这甚至可以从库外部,例如由用户完成。
要考虑的另一重要事项是您需要对结构的内部进行多少访问。使用枚举,您可以完全访问结构中存储的所有数据。如果你想要写一个可以同时操作的功能Coordinate和Quaternion使用特点,那么你将是唯一的操作能够执行是那些所描述的Axes特征(在这种情况下,Shift和Fold)。例如,给出Axes您所给出的实现,就没有办法让您简单地(X,Y,Z)通过Axes接口检索元组。如果需要在某个时候这样做,则必须添加一个新方法。
在不了解更多有关如何计划使用这些类型的信息的情况下,很难确定其中哪个选项是更好的选择,但是如果是我,我可能会使用一个枚举。最终,它很大程度上取决于偏好,但是希望这可以使您对做出决定时要考虑的事情有所了解。
@Kwarrtz的答案中未提及的另一个差异是与内存相关的。
enums可以直接存储在堆栈上,而装箱的特征始终需要堆。也就是说,enum创建s很便宜,但装箱的特征却不是。enum即使您主要存储小变体,一个实例也总是与其最大变体一样大(在大多数情况下还要加上判别式)。在这种情况下,这将是一个问题:
enum Foo {
SmallVariant(bool),
BigVariant([u64; 100]),
}
Run Code Online (Sandbox Code Playgroud)
如果要在向量中存储N个这种类型的实例N*(100*sizeof::<u64> + sizeOfDiscriminant),则即使向量仅包含SmallVariants ,向量也总是需要字节的内存。
如果您使用的是盒装特征,则矢量将使用N * sizeOfFatPointer == N * 2 * sizeof::<usize>。