这个问题在这里已有答案:
我看到了一些相关的问题(比如this和this),但我希望我的默认方法用例足够独特,可以提出一个稍微不同的问题。以下最小示例工作和输出"Sheriff Ted" shot "Billy the Kid"!
:
#[derive(Debug)]
struct Actor {
name: String,
}
fn main() {
let cop = Actor {
name: String::from("Sheriff Ted"),
};
let robber = Actor {
name: String::from("Billy the Kid")
};
println!("{:?} shot {:?}!", cop.name, robber.name); // without the trait. with:
// cop.shoot(&robber);
}
//pub trait Shoot {
// fn shoot(&self, other: &Actor) {
// println!("\n{:?} shot {:?}!",
// &self.name,
// &other.name,
// )
// }
//}
//
//impl Shoot for Actor {}
正如您所看到的,我想要在Shoot
结构中传递shoot
实现和它包含的Actor
方法。当我取消注释Shoot
特性,它在Actor
上的实现,以及调用cop.shoot(&robber)
时,我得到了相关问题的错误信息,以及:error[E0609]: no field 'name' on type '&Self'
。
我的第一个想法是在默认方法的签名中指定&self: Actor
,但这会产生分隔符错误,因此在语法上无效。
我认为这个问题是独一无二的,因为其他问题似乎误解了他们指定的泛型如何影响他们的预期类型,而在我的情况下,我不明白为什么我不能访问我试图实现的结构中的字段默认方法。
这适用于只有Actor
s需要shoot
的情况,但我正在寻找一种方法来应用这种行为(现在,只是println
ing)跨多种类型。
impl Actor {
fn shoot(&self, other: &Actor) {
println!("\n{:?} shot {:?}!",
self.name,
other.name,
)
}
}
您没有尝试在任何结构上实现默认方法;你正在为这个特质实现它。因此,您无法访问任何结构上的任何字段;你只能访问特质要求的东西。
特征方法的默认实现意味着任何实现特征的非默认方法的类型都可以使用默认方法,无论它看起来如何。但是你希望实现类型除了特征要求之外还有一个name
字段(顺便说一下,它没有任何要求)。
这根本不是一个有效的假设。
我想知道你为什么要在这里使用一个特性。如果你可以在self
方法中要求Actor
为shoot
,为什么它是一种特征方法?为什么它不是没有任何特征的Actor
结构的固有方法?
在阅读了Sebastian的回复之后,我认为“回答”是:你不能在traits的默认方法中命名struct字段,因为在实现trait之前你不知道struct可能具有哪些字段。所以你要定义一个(抽象?)方法签名,然后在它实现时使其具体化。就我而言,这有效:
trait Shoot {
fn shoot(&self, other: &Actor);
}
impl Shoot for Actor {
fn shoot(&self, other: &Actor) {
println!("\n{:?} shot {:?}!",
self.name,
other.name,
);
}
}
仍然有兴趣知道我是否可以约束一个特征只适用于具有某些字段的结构,如果这与“特征边界”不同。 (我认为......)