如何在不重复方法的情况下实现结构的多个特征?

use*_*211 2 traits rust

下面的代码工作正常,但是我要重复很多次,我认为这不是真的。例如,我正在实现两个特征Square,这感觉不对!coordinate()在特征和实现中也重复该功能。

有没有一种方法可以实现此代码而又不会经常重复自己?是否可以实现以下两个特征:

impl BasicInfo && Sides for Square {
    ....
} 
Run Code Online (Sandbox Code Playgroud)

上面的代码不起作用,这只是一个想法。当一个函数可以应用于多个结构时,是否可以在特征中只定义一次BasicInfo并访问它。

fn main() {
    let x_1: f64 = 2.5;
    let y_1: f64 = 5.2;
    let radius_1: f64 = 5.5;
    let width_01 = 10.54;

    let circle_01 = Circle { x: x_1, y: y_1, radius: radius_1 };
    let square_01 = Square { x: x_1, y: y_1, width: width_01, sides: 4 };

    println!("circle_01 has an area of {:.3}.", 
        circle_01.area().round());
    println!("{:?}", circle_01);
    println!("The coordinate of circle_01 is {:?}.\n", circle_01.coordinate());
    println!("coordinate of square_01: {:?} has an area of: {} m2 and also has {} sides.", 
        square_01.coordinate(), 
        (square_01.area() * 100.0).round() / 100.0,
        square_01.has_sides() );
}

#[derive(Debug)]
struct Circle {
    x: f64,
    y: f64,
    radius: f64,
}

struct Square {
    x: f64,
    y: f64,
    width: f64,
    sides: i32,
}

trait BasicInfo {
    fn area(&self) -> f64;
    // coordinate() is declared here, but not defined. Is it possible to define it here and still be able to access it when I want it.
    fn coordinate(&self) -> (f64, f64);
}

trait Sides {
    fn has_sides(&self) -> i32;
}

impl BasicInfo for Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * (self.radius * self.radius)
    }
    // coordinate() gets defined again, and looks like repeating code
    fn coordinate(&self) -> (f64, f64) {
        (self.x, self.y)
    }
}

impl BasicInfo for Square {
    fn area(&self) -> f64 {
        self.width.powf(2.0)
    }
    // coordinate() gets defined again, and looks like repeating code
    fn coordinate(&self) -> (f64, f64) {
        (self.x, self.y)
    }
}

impl Sides for Square {
    fn has_sides(&self) -> i32 {
        self.sides
    }
}
Run Code Online (Sandbox Code Playgroud)

Pao*_*lla 5

对于第二个问题(避免重复相同的实现coordinate),我想向您展示基于宏的解决方案。

有趣的是,它让您拥有3个特征而不是2个特征,因此它的方向与第一个问题的方向完全相反。我想你不可能拥有一切!:)

// factoring out the Coordinates trait from BasicInfo
trait Coordinates {
    fn coordinate(&self) -> (f64, f64);
}

// but we can require implementors of BasicInfo to also impl Coordinates
trait BasicInfo: Coordinates {
    fn area(&self) -> f64;
}

// helper macro to avoid repetition of "basic" impl Coordinates
macro_rules! impl_Coordinates { 
    ($T:ident) => {
        impl Coordinates for $T {
            fn coordinate(&self) -> (f64, f64) { (self.x, self.y) }
        }
    }
}

#[derive(Debug)]
struct Circle {
    x: f64,
    y: f64,
    radius: f64,
}

#[derive(Debug)]
struct Square {
    x: f64,
    y: f64,
    width: f64,
    sides: i32,
}

// the macro here will expand to identical implementations
// for Circle and Square. There are also more clever (but a bit
// harder to understand) ways to write the macro, so you can
// just do impl_Coordinates!(Circle, Square, Triangle, OtherShape)
// instead of repeating impl_Coordinates!
impl_Coordinates!(Circle);
impl_Coordinates!(Square);


trait Sides {
    fn has_sides(&self) -> i32;
}

impl BasicInfo for Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * (self.radius * self.radius)
    }
}

impl BasicInfo for Square {
    fn area(&self) -> f64 {
        self.width.powf(2.0)
    }
}

impl Sides for Square {
    fn has_sides(&self) -> i32 {
        self.sides
    }
}
Run Code Online (Sandbox Code Playgroud)


Seb*_*edl 1

为一种类型实现多个特征并没有什么问题;事实上这很常见。

我也不明白你coordinate在特征和实现中重复的意思。该函数在特征中声明并在 impl 中实现,就像所有其他特征函数一样。您的意思是该函数的实现在 Square 和 Circle impls 中是相同的吗?尽管可能有更好的方法,但宏可以帮助您。