如何访问特征的默认方法定义中的结构字段?



我看到一些相关的问题(比如这个和这个),但我希望我的默认方法用例足够独特,可以提出一个稍微不同的问题。 以下最小示例工作并输出"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实现及其在Actor结构上包含的shoot方法。当我取消注释Shoot特征、它在Actor上的实现以及调用cop.shoot(&robber)时,我也会收到相关问题的错误消息:error[E0609]: no field 'name' on type '&Self'

我的第一个想法是在默认方法的签名中指定&self: Actor,但这会产生分隔符错误,因此在语法上无效。

我认为这个问题是独一无二的,因为其他问题似乎误解了他们指定的泛型如何掩盖其预期类型,就我而言,我不明白为什么我无法访问我尝试实现默认方法的结构中的字段。

这适用于只有Actor需要shoot的情况,但我正在寻找一种将这种行为(现在,只是printlning)应用于多种类型的方法。

impl Actor {
fn shoot(&self, other: &Actor) {
println!("n{:?} shot {:?}!",
self.name,
other.name,
)
}
}

您不是在尝试在任何结构上实现默认方法;您正在为特征实现它。因此,您无法访问任何结构上的任何字段;您只能访问特质所需的内容。

特征方法的默认实现意味着实现特征的非默认方法的任何类型的都可以使用默认方法,无论它看起来如何。但是你希望实现类型除了特征需要什么之外还有一个name字段(顺便说一下,它不需要任何东西)。

这根本不是一个有效的假设。

我想知道你为什么在这里使用特质。如果你同意要求selfshoot方法中Actor,为什么它是一种特质方法?为什么它不是没有任何特征的Actor结构的固有方法?

在阅读了塞巴斯蒂安的回应后,我认为"答案"是:你不能在特征的默认方法中命名结构字段,因为在实现特征之前你不知道结构可能具有哪些字段。因此,您需要定义一个(抽象的?)方法签名,然后在实现时使其具体化。 就我而言,这有效:

trait Shoot {
fn shoot(&self, other: &Actor);
}
impl Shoot for Actor {
fn shoot(&self, other: &Actor) {
println!("n{:?} shot {:?}!",
self.name,
other.name,
);
}
}

仍然有兴趣知道我是否可以将特征限制为仅应用于具有某些字段的结构,以及这是否与"特征边界"不同。 (我认为是的...

最新更新