繁体   English   中英

在结构中使用泛型并通过特征实现

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

我想要实现的是我可以发送f32i32 ,而无需创建两个不同的 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变量名)。

我想要实现的是我可以发送f32i32 ,而无需创建两个不同的 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM