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

时间:2019-04-14 16:24:01

标签: rust traits

我看到了一些相关的问题(例如thisthis),但我希望我的默认方法用例足够独特,可以提出一个稍有不同的问题。以下最小示例可以工作并输出"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个需要shoot的情况,但是我正在寻找一种在多种类型上应用此行为(目前仅println)的方法。

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

2 个答案:

答案 0 :(得分:2)

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

trait方法的默认实现意味着,实现trait的非默认方法的任何类型都可以使用default方法,而不管其外观如何。但是您希望实现类型除了特征需要什么(顺便一无所求)之外,还有一个name字段。

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

我不知道您为什么在这里使用所有特征。如果您可以在self方法中要求Actorshoot,那么为什么它是特征方法呢?为什么它不是Actor结构的固有方法而没有任何特征?

答案 1 :(得分:0)

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

trait Shoot {
    fn shoot(&self, other: &Actor);
}

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

仍然有兴趣知道我是否可以将特征限制为仅应用于具有某些字段的结构,并且该特征是否不同于“特征边界”。 (我想是……)