[英]Using a generic in a struct and implementing via a trait
我有这样定义的结构
struct Shape<T> {
line_one: T,
line_two: T,
}
我正在尝试创建一个简单的特征和实现,它使用这个结构来计算一些简单的数学。
我的 trait 和 impls 看起来像这样
trait Calculate<T: Mul<Output = T>> {
fn calc(&self, Shape: T) -> T;
}
impl<T> Calculate<T> for Shape<T> {
fn calc(&self, Shape: T) -> T {
self.line_one * 2 + self.line_two * 2
}
}
impl Calculate<i32> {
fn calc(&self) -> i32 {
self.line_one * 2 + self.line_two * 2
}
}
fn calc_fn<T: Calculate<i32>>(calculate: T) {
calculate.calc();
}
当我把它放到 Rust 的操场上时,编译失败,因为Mul
没有在impl Calculate<T>
。 但是,如果我将<T>
更改为<T: Mul<Output = T>>
,则会出现错误
<anon>:14:21: 14:22 error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `:`
<anon>:14 impl <T> Calculate<T: Mul<Output = T>> for Shape<T>
我不知道如何在impl Calculate<T>
为T
实现Mul
。
我想要实现的是我可以发送f32
或i32
,而无需创建两个不同的 impl 定义,因此只需传入T
。
此语法不正确:
impl<T> Calculate<T: Mul<Output = T>> for Shape<T>
你要
impl<T: Mul<Output = T>> Calculate<T> for Shape<T>
我几乎总是建议使用where
子句; 我认为它读起来更好,可能有助于防止这种情况:
impl<T> Calculate<T> for Shape<T>
where T: Mul<Output = T>,
这只会解锁更多错误。 您正在尝试乘以2
,这是一个尚未完全确定的整数变量 - 是u8
吗? 是i32
吗? 限制并不是说T
可以乘以2
。 此外,您尝试将值添加在一起,但不能保证您可以添加类型T
。
impl Calculate<i32>
和calc_fn
块没有意义; 您不太可能想要为特征实现函数,并且您不会在后者中提供Shape
。 该 trait 也不使用Shape: T
参数(并且 Rust 无论如何都使用snake_case
变量名)。
我想要实现的是我可以发送
f32
或i32
,而无需创建两个不同的 impl 定义,因此只需传入T
。
在这种情况下,它可能会更容易:
trait Calculate<T> {
fn calc(&self) -> T;
}
impl Calculate<i32> for Shape<i32> {
fn calc(&self) -> i32 {
self.line_one * 2 + self.line_two * 2
}
}
impl Calculate<f32> for Shape<f32> {
fn calc(&self) -> f32 {
self.line_one * 2.0 + self.line_two * 2.0
}
}
请注意,这些不是等价的! f64
具有浮点文字( 2.0
)而不是整数( 2
)。
如果您必须有一个泛型,您将需要将文字2
转换为类型T
或添加一个限制,即 T 可以乘以某个已知大小。 不幸的是, f64
不能在没有强制转换的情况下乘以任何整数值。
来自 num crate 的FromPrimitive
特性是这里的关键。 使类型Copy
也使实现更容易。
extern crate num;
use std::ops::{Add, Mul};
use num::FromPrimitive;
struct Shape<T> {
line_one: T,
line_two: T,
}
trait Calculate<T> {
fn calc(&self) -> T;
}
impl<T> Calculate<T> for Shape<T>
where T: Copy + FromPrimitive + Add<Output = T> + Mul<Output = T>,
{
fn calc(&self) -> T {
let two = T::from_u8(2).expect("Unable to create a value of two");
self.line_one * two + self.line_two * two
}
}
fn main() {
let s1 = Shape { line_one: 2, line_two: 3 };
let s2 = Shape { line_one: 2.0, line_two: 3.0 };
println!("{}", s1.calc());
println!("{}", s2.calc());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.