\n
TL;博士。是否可以为已经具有特征所需的所有方法的现有类型自动实现特征?
\n长版。假设我想要一个通用函数,可以对任何类似堆栈的类型执行堆栈操作。所以我有一个特点
\npub trait StackLike<T> {\n fn is_empty(&self) -> bool;\n fn pop(&mut self) -> Option<T>;\n fn push(&mut self, value: T);\n}\nRun Code Online (Sandbox Code Playgroud)\n我现在可以这样使用pub fn foo(s: &mut dyn StackLike<i32>) { s.push(42); }:到目前为止,一切都很好。
有几种现有类型已经满足我的特征,因此实现它很简单,例如
\nimpl<T> StackLike<T> for Vec<T> {\n fn is_empty(&self) -> bool { self.is_empty() }\n fn pop(&mut self) -> Option<T> { self.pop() }\n fn push(&mut self, value: T) { self.push(value) }\n}\n\nimpl<T, const N: usize> StackLike<T> for SmallVec<[T; N]> {\n fn is_empty(&self) -> bool { self.is_empty() }\n fn pop(&mut self) -> Option<T> { self.pop() }\n fn push(&mut self, value: T) { self.push(value) }\n}\nRun Code Online (Sandbox Code Playgroud)\n这可行,但有很多样板。这里绝对没有发生任何有趣的事情:方法名称、参数类型和返回类型 \xe2\x80\x94 一切都相同。
\n问题。是否可以避免拼写出所有这些同义反复的陈述,即执行类似于下面的代码片段的操作?
\n#[implement-trait-automagically]\nimpl<T> StackLike<T> for Vec<T>;\n\n#[implement-trait-automagically]\nimpl<T, const N: usize> StackLike<T> for SmallVec<[T; N]>;\nRun Code Online (Sandbox Code Playgroud)\n或者我可以以某种方式标记我的特征,以便所有可以满足它的类型自动满足它(类似于概念在 C++ 中的工作方式)?
\ncdh*_*wie 10
Rust 没有这种“鸭子类型”,但您可以将实现放在宏后面,以实现您既定的目标,即避免所有样板代码,同时保持实现相同且无错误:
pub trait StackLike<T> {
fn is_empty(&self) -> bool;
fn pop(&mut self) -> Option<T>;
fn push(&mut self, value: T);
}
macro_rules! stacklike_impl {
() => {
fn is_empty(&self) -> bool { self.is_empty() }
fn pop(&mut self) -> Option<T> { self.pop() }
fn push(&mut self, value: T) { self.push(value) }
}
}
impl<T> StackLike<T> for Vec<T> { stacklike_impl!(); }
impl<T, const N: usize> StackLike<T> for SmallVec<[T; N]> { stacklike_impl!(); }
Run Code Online (Sandbox Code Playgroud)