地址: https://kaisery.github.io/trpl-zh-cn/ch19-03-advanced-traits.html 如下是书中的原话: 这类似于泛型。那么为什么 Iterator trait 不像示例 19-13 那样定义呢?
pub trait Iterator<T> {
fn next(&mut self) -> Option<T>;
}
示例 19-13: 一个使用泛型的 Iterator trait 假想定义
区别在于当如示例 19-13 那样使用泛型时,则不得不在每一个实现中标注类型。这是因为我们也可以实现为 Iterator for Counter,或任何其他类型,这样就可以有多个 Counter 的 Iterator 的实现。换句话说,当 trait 有泛型参数时,可以多次实现这个 trait,每次需改变泛型参数的具体类型。接着当使用 Counter 的 next 方法时,必须提供类型注解来表明希望使用 Iterator 的哪一个实现。 通过关联类型,则无需标注类型,因为不能多次实现这个 trait。对于示例 19-12 使用关联类型的定义,我们只能选择一次 Item 会是什么类型,因为只能有一个 impl Iterator for Counter。当调用 Counter 的 next 时不必每次指定我们需要 u32 值的迭代器。 ---------原话结束--------
我感觉这段解释不太对吧, 我impl Itertator for Counter实现也不用多次实现啊. 我觉得使用关联类型最大的好处避免了在trait中使用泛型, 可以作为一个trait对象使用.
评论区
写评论这么一想, 如果结构体用的泛型, 那么即使使用关联类型, 其实都还是可以有很多实现的. 不过这种情况下确实可以不必在调用函数的时候指定类型
--
👇
Grobycn: 要是在追加如下一种实现
那么以下代码会有不明确的类型
要是在追加如下一种实现
那么以下代码会有不明确的类型
如果是这样定义的Foo去实现Iterator, 那么只需要new的时候指定下类型就好了.
--
👇
Grobycn: 原文意思是,假如定义成
对于一个类型
Foo
,你可以impl Iterator<String> for Foo
,impl Iterator<Vec<u8>> for Foo
以及其它无穷种实现。当你调用
Foo::next
的时候,你需要指定泛型参数Foo::next::<Vec<u8>>(&mut foo)
。但是使用关联类型,避免了这种麻烦。
原文意思是,假如定义成
对于一个类型
Foo
,你可以impl Iterator<String> for Foo
,impl Iterator<Vec<u8>> for Foo
以及其它无穷种实现。当你调用
Foo::next
的时候,你需要指定泛型参数Foo::next::<Vec<u8>>(&mut foo)
。但是使用关联类型,避免了这种麻烦。
在官方的slice的标准库中, 也是使用了泛型去实现的Iterator的, 那么用泛型定义trait并没有什么问题, 最大的原因是使用泛型无法使用trait对象:
impl<T> Itertator for Counter<T>
这样实现trait