如何让Rust中Widget Trait的实现更具泛化性
问题描述
我定义了一个带泛型的Widget<T> trait:
pub trait Widget<T> { fn common(&self) -> &Common; fn value(&self) -> &T; fn value_mut(&mut self) -> &mut T; }
其中Common是已定义的自定义结构体,该trait要求通过.value()和.value_mut()返回与泛型<T>一致的不可变/可变引用。
另外我实现了受Numeric trait约束的NumberWidget<T>结构体,仅支持原始数字类型:
pub struct NumberWidget<T> { common: Common, value: T, range: RangeInclusive<T>, } impl<T: Numeric> NumberWidget<T> { pub fn new( // ... 省略实现细节 ) -> Self { // ... } }
我希望让NumberWidget实现Widget trait,但因为两者都带泛型参数,直接写impl Widget for NumberWidget不行。目前只能为每个数字类型单独写实现,比如:
impl Widget<f64> for NumberWidget<f64> { fn common(&self) -> &Common { &self.common } fn value(&self) -> &f64 { &self.value } fn value_mut(&mut self) -> &mut f64 { &mut self.value } } impl Widget<i64> for NumberWidget<i64> { fn common(&self) -> &Common { &self.common } fn value(&self) -> &i64 { &self.value } fn value_mut(&mut self) -> &mut i64 { &mut self.value } }
这种写法会产生大量重复代码。我尝试写impl Widget<T: Numeric> for NumberWidget<T>但编译报错:
trait takes 1 generic argument but 0 generic arguments were supplied expected 1 generic argument associated type bounds are unstable see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information associated type bindings are not allowed here associated type not allowed here cannot find type `T` in this scope
请问有没有办法不用为每个Numeric类型单独写impl,就能让NumberWidget<i64>、NumberWidget<usize>、NumberWidget<f32>等都实现Widget trait?
解决方案
你只需要调整泛型参数和约束的写法,把T的约束放在impl的泛型列表里,而不是写在Widget<T>的参数中。正确的实现代码如下:
impl<T: Numeric> Widget<T> for NumberWidget<T> { fn common(&self) -> &Common { &self.common } fn value(&self) -> &T { &self.value } fn value_mut(&mut self) -> &mut T { &mut self.value } }
为什么之前的写法错误?
你之前写的impl Widget<T: Numeric> for NumberWidget<T>不符合Rust的语法规则:
- 泛型参数的约束必须放在
impl关键字后的尖括号<>中,而不是附加在trait的泛型参数上。 - 当你写
Widget<T: Numeric>时,Rust会误以为你是在尝试绑定关联类型(而非使用泛型参数),这才触发了关于关联类型的报错。
这样写之后,所有满足Numeric约束的T类型,对应的NumberWidget<T>都会自动实现Widget<T> trait,无需逐个类型手动编写impl。
内容的提问来源于stack exchange,提问作者Anselan
相关产品推荐
相关产品推荐

