从函数返回特征值

9
我有两个枚举类型,其中NormalColourBoldColour都实现了Colour特性。它们包含BlueBoldGreen等值。
我想从同一个函数返回这两种类型的值,将它们视为Colour值,在结果上调用paint函数,但我无法强制Rust编译器为我完成这个过程。我希望能够像这样编写代码:
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
    }
}

为使函数起作用,我需要返回什么类型?

最终,我想让更多的类型实现Colour,这就是为什么我不想把这两个枚举合并成一个大枚举的原因。

2个回答

7
答案是trait对象。这意味着您将使用Box作为您的类型;裸Color不是可实例化类型。您可以使用as运算符将Box对象转换为Box:Box::new(NormalColour::White) as Box。在许多地方,这是不必要的(只需编写Box::new(NormalColour::White)并且它可以自动强制转换为Box),但有时仍然是必要的。
但是,如果您可以将其作为枚举执行,则可能是一个更好的解决方案。

1
签名是什么样子的? - Juan Ibiapina
@JuanIbiapina:当时它是~Colour的返回类型;现在,它是Box<Colour>。实际上,&'static Colour也可能起作用。 - Chris Morgan
@ChrisMorgan 我的设计中有一组对象类型,它们可以通过共同特征进行关联,使用枚举将是一种灾难,因为枚举中会有大约50-75个成员。此外,我希望在远程用户拼写错误的情况下返回Option<SomethingLikeTheTrait>。你能提供一些建议吗? - cardiff space man
@cardiffspaceman:枚举中拥有很多成员并不是什么灾难。至于你提出的其他问题,我不知道你的意思。这是另外一个问题,并且不适合在回答别人问题的评论中讨论。 - Chris Morgan

2
上面的答案建议:
fn file_colour(stat: &io::FileStat) -> Box<Colour> { /* ... */ }

这个方法是可行的,但你需要在所有的返回值前加上 Box::new()

然而,在 Rust 1.26 中,你可以直接使用

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

并且只需返回该值。不需要使用Box

有时候,你仍然需要一个特质对象。更多细节请参见重复内容。 - Shepmaster
同意@Shepmaster。感谢标记重复内容。 - Sean Perry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接