我在Rust stable中定义了一个crate API(截至目前为1.2版),并且对于定义我自己的类似字符串的类型的最佳实践感到困惑。
例如,我有一个包装字符串的Foo
类型。
pub struct Foo(String);
我的API隐藏了Foo
实例的构造,而且,因为元组字段是私有的,所以应用程序不能错误地为自己构造无效的Foo
值。这意味着我的API限制应用程序仅使用有效的Foo
值。到现在为止还挺好。
但是,我希望应用程序能够使用Foo
实例,就像它是一个字符串 - 说,打印它,记录它,将其写入文件,将其传递给接受&str
的第三方包,通过构建副本to_string()
和变异副本等。简而言之,我希望应用程序能够“抛弃”Foo
-ness并使用对底层字符串的引用。由于应用程序无法将原始字符串转换回Foo
实例,因此保留了类型安全性。
我的问题是:如果有什么转换特性,我的箱子应该为Foo
实现允许应用程序“抛弃”Foo
-ness并使用底层字符串作为原始字符串?重要的是Foo
转换为&str
,以避免任何不必要的复制基础字符串。
例如,怎么样?
impl AsRef<str> for Foo
这是正确的做法吗?是否足以成为惯用语?我应该考虑为Foo
实施任何其他转换特征吗?
如果Foo
在语义上是一个字符串,那么实现Deref<Target = str>
(或可能是Deref<Target = String>
和DerefMut
)是主要的事情。这将允许&Foo
强迫&str
,所以你可以写像&*foo
这样的东西,以获得&str
和Foo
等foo.starts_with("bar")
,调用str
定义的方法。
实施AsRef
对某些事情也会有所帮助。 Borrow
是你可能想要的另一件事,though there are things to consider before doing so。