下面的代码工作正常,但是我要重复很多次,我认为这不是真的。例如,我正在实现两个特征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)
对于第二个问题(避免重复相同的实现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)
为一种类型实现多个特征并没有什么问题;事实上这很常见。
我也不明白你coordinate在特征和实现中重复的意思。该函数在特征中声明并在 impl 中实现,就像所有其他特征函数一样。您的意思是该函数的实现在 Square 和 Circle impls 中是相同的吗?尽管可能有更好的方法,但宏可以帮助您。
| 归档时间: |
|
| 查看次数: |
2838 次 |
| 最近记录: |