英文:
How to make implementations of traits more generic
问题
You can use Rust's generic trait implementations to avoid having to implement Widget
for each possible numeric type explicitly. Here's an example of how you can do it:
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
}
}
This code defines a generic implementation of the Widget
trait for NumberWidget<T>
where T
is any type that satisfies the Numeric
trait bound. This way, you can use NumberWidget
with various numeric types without the need for explicit implementations for each type.
英文:
So I have a trait called "Widget" which is quite simple:
pub trait Widget<T> {
fn common(&self) -> &Common;
fn value(&self) -> &T;
fn value_mut(&mut self) -> &mut T;
}
Other than the custom struct Common
(defined elsewhere), it should be clear that the Widget trait simply specifies that an immutable or mutable reference can be returned using .value()
and .value_mut
functions, and this will be of the same type as the Widget itself (T
).
So, for example, I have a "NumberWidget", like this...
pub struct NumberWidget<T> {
common: Common,
value: T,
range: RangeInclusive<T>,
}
impl<T: Numeric> NumberWidget<T> {
pub fn new(
...etc.
...which is constrained by the trait bound Numeric
- it can only apply to primitive numbers.
I want NumberWidget
to satisfy the trait Widget
, of course. But I cannot simply write...
impl Widget for NumberWidget {
Because both Widget and NumberWidget need a generic argument.
So let's say I want to have integer and float versions of "NumberWidget". The only way I have so far which works and compiles is to implement both explicitly:
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
}
}
This is fine for just two variations, but it's already more duplication than I feel comfortable with. I guess I'm looking for something like:
impl Widget<T: Numeric> for NumberWidget<T>
But this is not valid:
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
.etc. etc.
Is there a way to construct instances such as NumberWidget<i64>
, NumberWidget<usize>
, NumberWidget<f32>
, etc. without having to implement impl NumberWidget<i64> for Widget<i64>
, etc. explicitly for every possible Numeric type?
答案1
得分: 2
你只是把类型参数放错了地方,你要找的是这样的:
impl<T: Numeric> Widget<T> for NumberWidget<T> {
// ^^^^^^^^^^^^ 类型参数应该放在 impl 块自身上
fn common(&self) -> &Common {
&self.common
}
fn value(&self) -> &T {
&self.value
}
fn value_mut(&mut self) -> &mut T {
&mut self.value
}
}
英文:
You've merely placed the type parameter in the wrong place, you're looking for this:
impl<T: Numeric> Widget<T> for NumberWidget<T> {
// ^^^^^^^^^^^^ The type parameter goes on the impl block itself
fn common(&self) -> &Common {
&self.common
}
fn value(&self) -> &T {
&self.value
}
fn value_mut(&mut self) -> &mut T {
&mut self.value
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论