【问题标题】:How do I access struct fields within default method definitions of traits? [duplicate]如何访问特征的默认方法定义中的结构字段? [复制]
【发布时间】:2019-04-14 16:24:01
【问题描述】:

我看到了一些相关的问题(如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 实现和它包含在Actor 结构上的shoot 方法传授给它。当我取消注释Shoot 特征、它在Actor 上的实现以及调用cop.shoot(&robber) 时,我也收到了与问题相关的错误消息:error[E0609]: no field 'name' on type '&Self'

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

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

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

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

【问题讨论】:

  • 我相信Is it possible to access struct fields from within a trait?的答案已经回答了您的问题。如果您不同意,请edit您的问题来解释差异。否则,我们可以将此问题标记为已回答。
  • @Shepmaster 我在问题顶部引用的那些答案都没有明确说明(无论如何对我而言)结构字段无法从默认方法定义访问,因为错误假设struct 将具有该字段(仍然在探索如何使用绑定来确保使用具有所述字段的结构类型)。试图在下面的回答中找到这种区别。如果我错了,那么我们可以标记为骗子。编辑:我现在看到了,default implementation of a trait (i.e. defining a method body within the trait), then no, you can't access fields.
  • 回复也很好,here:A trait cannot expose a field/attribute...(cont)

标签: rust traits


【解决方案1】:

您没有尝试在任何结构上实现默认方法;您正在为特征实施它。因此,您无法访问任何结构上的任何字段;您只能访问 trait 要求的内容。

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

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

我想知道你为什么要在这里使用一个特性。如果您可以在shoot 方法中要求selfActor,那么为什么它是一种特征方法?为什么它不是 Actor 结构的固有方法,没有任何特征?

【讨论】:

  • 我缩减了我的示例以使其最小化,但也有许多其他的东西。枪、大炮或船舶结构(所有这些都将有一个名称字段)可以在它们上实现这个特性......这有意义吗?如果不是,您是说我会将特征的实现仅限于具有此名称字段的事物吗? (根据您的建议添加了一个小修改...)
【解决方案2】:

在阅读了 Sebastian 的回复后,我认为“答案”是:您不能在 trait 的默认方法中命名结构字段,因为在实现 trait 之前您不知道结构可能具有哪些字段。因此,您将定义一个(抽象的?)方法签名,然后在实现时使其具体化。就我而言,这是可行的:

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

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

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

【讨论】:

  • 你可以添加一个特征NamedShooter,它定义了一个getter方法fn name(&self) -> &str。然后,您可以为NamedShooter 实现添加Shoot 的一揽子实现。
猜你喜欢
  • 2017-05-07
  • 1970-01-01
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-08
  • 1970-01-01
相关资源
最近更新 更多