1.声明了一个范型结构体:
struct Complex<T> {
re: T,
im: T
}
2.为结构体实现+操作符操作,即实现 Add trait
impl<T: Add<T, Output=T>> Add for Complex<T> {
type Output = Complex<T>;
fn add(self, rhs: Complex<T>) -> Self::Output {
Complex { re: self.re + rhs.re, im: self.im + rhs.im }
}
}
3.问题就出现在这个 T: Add<T, Output=T>,系统的 Add trait的定义为 pub trait Add<Rhs = Self> {...}
明明范型参数只有一个 Rhs,并且默认值是Self,为什么那段代码可以写成 Add<T, Output=T>,这里明明有 2 个范型参数呢,一个T,一个Output,有点看不明白,另外Output=T应该对Output设置默认值吧,但是方法定义里面又定义了type Output = Complex<T>,感觉好绕。
1
共 5 条评论, 1 页
评论区
写评论最后放一下可执行的rust playground代码,是我上面回复里面用到的例子。
rust playground
问题大体可以分成两个部分,第一是对于
Addtrait的理解,第二是对于impl<T>的理解。首先,
Addtrait是这么定义的。所以在形如
a+b=c的式子中,涉及了三种类型:加号左边a是Self类型,加号右边b是Rhs类型,最终的结果c是Output类型。这三种类型之间没有任何联系(尽管在默认情况下,Rhs和Self是同一种类型,但它们可以是不同的)。所以我们可以实现下面这种这种例子。其中Output类型被称为associate type,因为当加号左右两边的类型已知时,结果的类型也应当唯一确定。关于associate type的更多内容,请阅读The book 19.2。然后是关于
impl<T>的理解。我把Complex的例子修改如下(和原问题中的代码不是一回事了)。用where来表明trait bound会更清晰一点。上面的前三行代码读作:
“如果
T和U之间可以做加法运算,那么实现Complex<T>和Complex<U>之间的加法。”上面的第五行代码读作:
“把
T+U的结果类型记作K,则Complex<T>+Complex<U>的结果类型是Complex<K>。”最后我们回到原本的问题上来,题目中的代码读作:
“如果
T和T之间可以做加法运算,而且结果的类型也是T,那么实现Complex<T>和Complex<T>之间的加法,其结果类型是Complex<T>。”看了一本书,精通rust(第二版),里面的事例代码。
--
👇
ges-AS: Add里面的Output是关联类型,必须要指定,因为有计算结果与左右两个数据类型不一样的可能(比如-1开方) T的Add和Complex的Add要分开来看,impl里面都是属于描述Complex的,外面是描述T的 (ps:话说为什么要搞一个范型,直接f64不行吗)
Add里面的Output是关联类型,必须要指定,因为有计算结果与左右两个数据类型不一样的可能(比如-1开方) T的Add和Complex的Add要分开来看,impl里面都是属于描述Complex的,外面是描述T的 (ps:话说为什么要搞一个范型,直接f64不行吗)
Output 是 associated type