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
问题大体可以分成两个部分,第一是对于
Add
trait的理解,第二是对于impl<T>
的理解。首先,
Add
trait是这么定义的。所以在形如
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