Traits as a return value from a function [duplicat

2019-01-20 08:39发布

This question already has an answer here:

I have two enums, NormalColour and BoldColour, both of which implement the Colour trait. They contain Blue, BoldGreen, and so on.

I'd like to return values of both of these types from the same function, treating them as though they're just a Colour value, calling the paint function on the result, but I can't find a way to coerce the Rust complier into doing this for me. I'd like to be able to write something like this:

pub trait Colour {
    fn paint(&self, input: &str) -> String;
}

fn file_colour(stat: &io::FileStat) -> Colour {
    if stat.kind == io::TypeDirectory {
        Blue
    } else if stat.perm & io::UserExecute == io::UserExecute {
        BoldGreen
    } else {
        White
    }
}

What type do I have to make the function return for it to work?

I'll eventually like to make more types implement Colour, which is why I'm not interested in just turning the two enums into one big enum.

标签: traits rust
2条回答
走好不送
2楼-- · 2019-01-20 08:52

The answer is trait objects. This means that you will work with Box<Colour> as your type; bare Colour is not an instantiable type. You can cast Box<T> objects to Box<Colour> with the as operator: Box::new(NormalColour::White) as Box<Colour>. In many places this is not necessary (just write Box::new(NormalColour::White) and it can be automatically coerced to Box<Colour>), but sometimes it will still be necessary.

Still, if you can do it as an enum, that will probably be a nicer solution.

查看更多
等我变得足够好
3楼-- · 2019-01-20 09:12

The answer above suggests:

fn file_colour(stat: &io::FileStat) -> Box<Colour> { /* ... */ }

which works, but you need to wrap all of the returns in a Box::new() call.

However, in Rust 1.26 you can now say

fn file_colour(stat: &io::FileStat) -> impl Colour { /* ... */ }

and simply return the value. No Box needed.

查看更多
登录 后发表回答