下面的代码运行得很好,但我重复了很多
而且我认为这不是真的很乡村。例如,我正在为Square
实现两个特征,这感觉不对!此外,函数coordinate()
在特征和实现中重复。
有没有办法实现这段代码而不经常重复自己?是否可以实现以下两个特征:
impl BasicInfo && Sides for Square {
....
}
上面的代码不起作用,这只是一个想法。当函数可以应用于多个结构时,是否可以在特征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
}
}
答案 0 :(得分:4)
第二个问题(避免重复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
}
}
答案 1 :(得分:1)
为一种类型实现多个特征没有错;事实上它很常见。
我也不会通过重复coordinate
这个特性和impl来理解你的意思。该函数在trait中声明并在impl中实现,就像所有其他trait函数一样。你的意思是Square和Circle impls中函数的实现是一样的吗? Macros会帮助你,尽管可能有更好的方法。
答案 2 :(得分:1)
免责声明:在撰写本文时,有两个问题捆绑在一起,而后者与标题不符。所以按照标题......
是否可以一次实现多个特征?
impl BasicInfo && Sides for Square { .... }
否强>
单独实现它们的开销相对较低,对于更复杂的情况,当需要约束时,可能无法为每个特征设置不同类型的约束。
话虽这么说,你可以打开一个RFC建议实现这个,然后让社区/开发者决定他们是否觉得值得实现。