简体   繁体   中英

Is it possible to reference enum variant of itself with another variant?

Is it possible to reference a variant of a enum, by another variant of the same enum in Rust?

Some imaginary code:

enum Message{
   Text(String),
   Secret(Self::Text)
}

Unfortunately, you can't. Message is a type, but Message::Text is not, and can't be used where types are used.

In this case the trivial solution is to just have Secret hold a String . However, assuming your real use case is a bit more complicated, the general strategy is to pull it out into another struct:

enum Message {
  Text(MessageData),
  Secret(MessageData),
}

struct MessageData {
  foo: Bar,
  // lots of other fields
}

Yes, it is possible! The Box type can wrap other types, allowing you to have self-referential types. This is needed in scenarios like linked lists.

I don't believe that you can specify that it wraps a specific variant though, so this is slightly different than what you asked for.

Here's an example with a little demonstration of hiding the secret!

use std::fmt;

enum Message {
   Text(String),
   Secret(Box<Self>)
}

impl fmt::Display for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let contents = match self {
            Message::Text(message) => message.to_string(),
            Message::Secret(_) => "(hidden)".to_string(),
        };
        write!(f, "{}", contents)
    }
}

fn main() {
    let message = Message::Text("Hello world".to_string());
    let secret = Message::Secret(Box::new(Message::Text("Don't read me!".to_string())));
    
    println!("Message: {}", message);
    println!("Secret: {}", secret);
}

Here's a playground link using the same code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=292286f473550a38fd24924dfafe7bfe

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM