调用特征的关联函数时如何指定关联类型<Item=...>?
Posted
技术标签:
【中文标题】调用特征的关联函数时如何指定关联类型<Item=...>?【英文标题】:How to specify associated type <Item=...> when calling associated function of a trait? 【发布时间】:2022-01-17 15:47:30 【问题描述】:我有这个锈代码playground:
use itertools::repeat_n,RepeatN;
pub trait MyIterator: Iterator
fn fill1(elem: Self::Item, n1: usize) -> RepeatN<Self::Item>
where
Self::Item: Clone,
repeat_n(elem, n1)
我的问题是我无法调用此方法,因为 rustc 无法推断类型。
// error[E0284]: type annotations needed
// let r: RepeatN<char> = MyIterator::fill1('a', 5);
// ^^^^^^^^^^^^^^^^^ cannot infer type
// note: cannot satisfy `<_ as Iterator>::Item == _`
let r: RepeatN<char> = MyIterator::fill1('a', 5);
我试过了,但它没有编译:
// error[E0229]: associated type bindings are not allowed here
let r: RepeatN<char> = MyIterator::<Item=char>::fill1('a', 5);
如何在此调用中指定Item
的类型?或者特征之外的函数(如itertools::repeat_n
)是这里最好的方法?
【问题讨论】:
既然不使用self
,那你为什么要把fill1
放在一个trait中呢?为什么不直接打电话给repeat_n
?对我来说就像x/y problem。
嗯,MyIterator
有更多的方法可以采用self
或&mut self
。我也有fn fill2(elem: Self::Item, n1: usize, n2: usize) -> RepeatN<RepeatN<Self::Item>> /*...*/
、fill3
等。
MyIterator
的目的是提供很多实用方法。
虽然理论上可以在 trait 中使用不采用 self
的方法,但需要在具体类型(例如 playground)上调用它们,因为实现 trait具体类型可以覆盖它们。 → 我的建议是让它们像 fn<T: Clone> fill1 (elem: T, n: usize) -> RepeatN<T> …
这样独立的通用函数
谢谢。如果您写该评论作为答案,我很乐意接受。
【参考方案1】:
好吧,你还没有为任何类型实现 trait,所以实际上不存在 fill1
函数。
如果您为实现Iterator<Item = char>
的某些类型实现MyIterator
,例如std::iter::Empty<char>
,那么您将能够通过该类型调用fill1
。
use std::iter::Empty;
impl MyIterator for Empty<char>
fn main()
let r: RepeatN<char> = Empty::fill1('a', 5);
然而,这是没有意义的。你会注意到Empty
在实际的函数定义中没有任何作用——它可以是任何迭代器。此外,对于其他 Self
类型,这种行为没有合理的概括。这就是为什么itertools::repeat_n
不是Itertools
特征的成员:它作为特征函数是无意义的,因为它不是多个迭代器类型共享的行为的概括。
在 Rust 中,与其他一些语言不同,并非所有东西都必须是类的成员。如果你只是想把fill1
和相关的东西放在一个共同的namespace中,直接使用模块,这是代码组织的最基本单位。
mod my_iterator
use itertools::repeat_n, RepeatN;
fn fill1<T>(elem: T, n1: usize) -> RepeatN<T>
where
T: Clone,
repeat_n(elem, n1)
【讨论】:
以上是关于调用特征的关联函数时如何指定关联类型<Item=...>?的主要内容,如果未能解决你的问题,请参考以下文章
背水一战 Windows 10 (99) - 关联启动: 关联指定的文件类型, 关联指定的协议