我有一个库,它曾经为FlatMap
实现了顶级公共特征(称之为Option
)。现在我已经重构了我的库并将该特征移动到名为option
的子模块中,并且通过将FlatMap
公开导入到顶级包中来确保向后兼容性。我想提醒用户注意它被弃用的顶级特征。我尝试过以下方法:
pub mod option {
pub trait FlatMap<T> {}
}
#[deprecated(note="Use option::FlatMap instead")]
pub use option::FlatMap;
但是这不起作用:我现在可以use mylib::FlatMap
和use mylib::option::FlatMap
并且可以正常工作而不会发出警告。我想第一次使用生成弃用警告。
请注意,我不能使用这样的别名特征:
pub mod option {
pub trait FlatMap<T> {}
}
#[deprecated(note="Use option::FlatMap instead")]
pub trait FlatMap<T>: option::FlatMap<T> {}
impl<T> FlatMap<T> for Option<T> {}
因为我依赖从Option
到option::FlatMap
的隐式转换来向Option
实例添加方法,而隐式转换不适用于别名特征。
答案 0 :(得分:1)
能够在option::FlatMap
上调用Option
方法不是转换,隐式或其他方式 - 它只是方法的解析方式。如果特征是use
d,则可以在对象上解析特征方法,但顶级FlatMap
特征没有方法,因此它根本不向对象添加任何内容。
现在看来,在Rust中实现这一目标的最佳方法是将特征(带有所有内容)复制到顶层,注释它#[deprecated]
,并写一条毯子impl
遵循“真实”版本。
pub mod option {
pub trait FlatMap<T> {
type Item;
type FlatMap;
fn flat_map<F>(self, f: F) -> Self::FlatMap
where
F: FnOnce(Self::Item) -> T;
}
// ...
}
#[deprecated(note = "Use option::FlatMap instead")]
pub trait FlatMap<T> {
type Item;
type FlatMap;
fn flat_map<F>(self, f: F) -> Self::FlatMap
where
F: FnOnce(Self::Item) -> T;
}
#[allow(deprecated)]
impl<T, U> FlatMap<T> for U
where
U: option::FlatMap<T>,
{
type Item = U::Item;
type FlatMap = U::FlatMap;
fn flat_map<F>(self, f: F) -> Self::FlatMap
where
F: FnOnce(Self::Item) -> T,
{
option::FlatMap::flat_map(self, f)
}
}
任何使用“外部”FlatMap
的尝试都会生成弃用警告(playground link)。
这种方法的一个限制(除了详细程度)是两个特征不兼容作为特征对象(例如,你无法将&FlatMap
传递给期望&option::FlatMap
的函数。 )但是,这个特性无论如何都不是对象安全的,所以在这种情况下并不重要。
碰巧,您对flat_map
的定义 - 虽然是and_then
的概括 - 与several other {{3}的概括不同使用,包括languages。所以你可能想考虑重命名它。 (我认为map_or_default
符合名称,与Rust's own Iterator::flat_map
上提供的其他方法一致。)