[英]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.