如何在方法impl的枚举中返回字符串中的&str?

pho*_*ina 2 rust borrow-checker

我想返回城市/城镇/村庄的名称作为参考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,
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

操场

Vic*_*voy 5

如果您只想通过消费返回城市名称而不丢失对象,则应将其写为以下内容:

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());
}
Run Code Online (Sandbox Code Playgroud)

说明:

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

    fn name(self) -> &str {
    
    Run Code Online (Sandbox Code Playgroud)

    调用此类方法后,您将无法再使用该实例.如果要读取字符串,则应接受引用:

    fn name(&self) -> &str {
    
    Run Code Online (Sandbox Code Playgroud)

    这导致另一个问题

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

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

    CityType::City { ref name } => name,
    
    Run Code Online (Sandbox Code Playgroud)

    这个关键字说我们必须使用模式匹配和值的引用.

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

    let city = CityType::City { name: "NY".to_owned() };
    
    Run Code Online (Sandbox Code Playgroud)

对于你的评论:

问题更为笼统:如何将ref返回到一个没有生命周期说明符的String,因为它只要枚举就行.

在Rust中,你没有一生没有参考.决不.在某些情况下,编译器可以为您推断出生命周期,但也有一些情况,它会错误地执行或不符合您的预期.在这种情况下,例如:

fn name(&self) -> &str {
Run Code Online (Sandbox Code Playgroud)

这里寿命,编译器将以此为以下几点:

fn name<'a>(&'a self) -> &'a str {
Run Code Online (Sandbox Code Playgroud)

您的引用必须使用相同的生命周期并且可以使用它们.