特征中的默认构造函数实现

Rah*_*ahn 1 traits rust

PointVec2使用相同的变量和完全相同的构造函数定义:

pub struct Point {
    pub x: f32,
    pub y: f32,
}

pub struct Vec2 {
    pub x: f32,
    pub y: f32,
}

impl Point {
    pub fn new(x: f32, y: f32) -> Self {
        Self { x, y }
    }
}

impl Vec2 {
    pub fn new(x: f32, y: f32) -> Self {
        Self { x, y }
    }
}
Run Code Online (Sandbox Code Playgroud)

是否可以定义一个特征来实现构造函数?

到目前为止,我发现只能定义接口,因为内部变量未知:

pub trait TwoDimensional {
    fn new(x: f32, y: f32) -> Self;
}
Run Code Online (Sandbox Code Playgroud)

cam*_*024 5

您当然可以定义这样的特征,并为您的 2 个结构实现它,但是您必须编写两次实现。尽管特征可以提供函数的默认实现,但以下内容将不起作用:

trait TwoDimensional {
  fn new(x: f32, y: f32) -> Self {
    Self {
      x,
      y,
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

原因很简单。i32如果您为or()或 an实现此特征会发生什么enum

特征从根本上来说没有关于实现它们的底层数据结构的信息。Rust 不支持 OOP,并且试图强制它通常会导致丑陋、不惯用和性能较差的代码。

但是,如果您有一堆结构并且想要本质上“impl多次写入相同的内容而不复制/粘贴”,那么宏可能会很有用。这种模式在标准库中很常见,例如,其中有一些为所有整数类型实现的函数。例如:

macro_rules! impl_constructor {
  ($name:ty) => {
    impl $name {
      pub fn new(x: f32, y: f32) -> Self {
        Self {
          x, y
        }
      }
    }
  }
}

impl_constructor!(Point);
impl_constructor!(Vec2);
Run Code Online (Sandbox Code Playgroud)

这些宏在编译时扩展,因此如果您执行了无效的操作(例如impl_constructor!(i32),您将收到编译错误,因为宏扩展将包含i32 { x, y }.

就我个人而言,我仅在确实有大量类型需要实现时才使用宏。这只是个人喜好,但是手写块和宏生成impl块之间没有运行时差异。