使用Iced的过程中理解Rust的关联类型
关联类型(Associated type)
关联类型是Rust为了解决类型参数(type parameter)之间的依赖关系而引入的。清楚的解释引入动机的文章就是 RFC095 。
同时,这篇文章详细说明了如何引用关联类型。
一个实际的例子
我们在使用Iced(一个跨平台的GUI库)开发一个自定义样式的button的时候, 遇到了关联类型。
以下代码创建一个button对象,宽度80,高50,样式怎么输入呢?
| 1 |  | 
看看这个style方法的签名。
| 1 |  | 
style方法是Button结构体的一个关联方法。
Button结构体是一个组件,它有两个类型参数,Message和Renderer。
其中Renderer类型参数的Bound在where中明确
- Renderer: crate::Renderer   需要实现crate::Renderertrait.
- Renderer::Theme: StyleSheet 并且该crate::Renderertrait的Theme关联类型需要实现StyleSheettrait.
crate::Renderer trait如下,有一个Theme关联类型
| 1 |  | 
还是回到这个style方法pub fn style(mut self, style: <Renderer::Theme as StyleSheet>::Style) -> Self。
这个方法的入参style的类型是<Renderer::Theme as StyleSheet>::Style,这个PATH的前缀是
<Renderer::Theme as StyleSheet> 表示实现了Renderer trait的类型的Theme关联类型 
需要实现StyleSheet trait。
因此<Renderer::Theme as StyleSheet>::Style完整的含义就是 
- 某个渲染类型 SomeRenderer 实现了crate::Renderertrait.
- 某个样式板类型 SomeThemeType 实现了button::StyleSheet。
- 且 SomeRenderer::Theme = SomeThemeType
- <Renderer::Theme as StyleSheet>::Style就是 SomeThemeType::Style = < ?? >.
因此style方法的入参的实际类型就是SomeStyleSheet::Style的实际类型。所以我们要找到SomeRenderer和SomeThemeType。
- 先看crate::Renderertrait的实现类型有那些,可以看到Renderer<B, T>1 
 2
 3
 4
 5
 6
 7impl<B, T> iced_native::Renderer for Renderer<B, T>
 where
 B: Backend,
 {
 type Theme = T;
 ...
 ...
这个结构体如下,
| 1 |  | 
这个似乎就是我们要找的 SomeRenderer。但是这个Renderer<B, T>有两个类型参数,第二个就是Theme类型参数。还是没有看到
这个类型参数具体的类型是什么。继续看哪里使用了这个带有类型参数的结构体Renderer<B, T>。
| 1 |  | 
这里看到声明了一个新的类型iced_wgpu::Renderer,并且指定了Theme = iced_style::theme::Theme。
这个新的类型在哪里使用了呢?
| 1 |  | 
因此这个iced_wgpu::Renderer就是我们要找的SomeRenderer,而SomeRenderer::Theme就是
iced_style::theme::Theme就是我们要找的SomeThemeType。
- 接着看iced_style::theme::Theme类型如何实现button::StyleSheettrait 从这里可以看到 从这里可以看到SomeThemeType::Style = iced_style::theme::Button因此style方法的入参是iced_style::theme::Button, 是一个枚举类型。
| 1 |  | 
从定义可以看出,如果我们要实现自定义的样式就需要使用Button::Custom(Box::new(??)).
而button::StyleSheet<Style = Theme>类型意思是某类型实现了button::StyleSheet trait,
并且关联类型Style = iced_style::theme::Theme. 
所以我们可以写一个自定义的button样式了。
| 1 |  | 
style方法的入参就是Button::Custom(Box::new(ButtonStyle{}))。
最后style方法的使用如下
| 1 |  | 
关于Iced
Iced使用的Elm模型非常容易使用。我用它实现一个简单的计算器。

总结
关联类型是Rust非常重要的特性。如果不深入理解的话,编译的错误信息都看不明白。