【问题标题】:How can I return a &str from Strings in an enum in a method impl?如何在方法 impl 的枚举中从字符串返回 &str?
【发布时间】:2017-12-18 12:12:57
【问题描述】:

我想返回城市/城镇/村庄的名称作为对str 的引用。我可以在实现中指定生命周期,但也为枚举指定它会导致错误,因为它没有声明引用。

enum CityType {
    City { name: String /* ... */ },
    Town { name: String /* ... */ },
    Village { name: String /* ... */ },
}

impl CityType {
    fn name(self) -> &str {
        match self {
            CityType::City { name } => &name,
            CityType::Town { name, .. } => &name,
            CityType::Village { name } => &name,
        }
    }
}

playground

【问题讨论】:

  • 您希望name 方法具体做什么?它有多个问题,答案可能取决于您的意图。
  • @VictorPolevoy 在这种情况下只需将 ref 返回到字符串。问题更普遍:如何将 ref 返回到没有生命周期说明符的字符串,因为它的生命周期与枚举一样长。
  • 你需要(重新)阅读 Rust 书中的 What is ownership 章节。 name(self) 获得枚举的所有权,并在函数返回时释放枚举。您不能返回对已释放枚举的引用。

标签: rust borrow-checker


【解决方案1】:

如果你只想返回一个城市名称而不通过消费丢失对象,你应该这样写:

enum CityType {
    City { name: String },
    Town { name: String },
    Village { name: String },
}

impl CityType {
    fn name(&self) -> &str {
        match *self {
            CityType::City { ref name } => name,
            CityType::Town { ref name, .. } => name,
            CityType::Village { ref name } => name,
        }
    }
}

fn main() {
    let city = CityType::City { name: "NY".to_owned() };
    println!("Name of the city: {}", city.name());
}

解释:

  1. 首先,您的方法的签名指定您使用该对象:

    fn name(self) -> &str {
    

    调用此类方法后,您将无法再使用该实例。如果你想读取一个字符串,你应该接受一个引用:

    fn name(&self) -> &str {
    

    这会导致另一个问题

  2. match 应该在不移动对象的情况下工作,所以这里是*

    match *self {
    
  3. 您不应该从枚举数据中移出,因此ref 关键字会有所帮助

    CityType::City { ref name } => name,
    

    这个关键字表示我们必须使用带有值引用的模式匹配。

  4. main 中,您传递了&str,但您的枚举中的项目是String,因此这会导致类型不兼容错误。通过在字符串引用上调用 .to_owned() 方法,您可以从中创建一个新的 String 对象:

    let city = CityType::City { name: "NY".to_owned() };
    

您的评论:

这个问题更普遍:如何将 ref 返回到一个没有生命周期说明符的字符串,因为它的生命周期与枚举一样长。

在 Rust 中,您不能拥有没有生命周期的引用。绝不。在某些情况下,编译器可以为您推断出生命周期,但也有一些情况下它执行不正确或与您的预期不符。在这种情况下,例如:

fn name(&self) -> &str {

个生命周期,编译器将其视为如下:

fn name<'a>(&'a self) -> &'a str {

您的引用绑定到相同的生命周期,并且可以使用。

【讨论】:

  • 感谢您的解释。这正是我的用例。
猜你喜欢
  • 2018-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多