调用特征的关联函数时如何指定关联类型<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&amp;mut self。我也有fn fill2(elem: Self::Item, n1: usize, n2: usize) -&gt; RepeatN&lt;RepeatN&lt;Self::Item&gt;&gt; /*...*/ fill3等。 MyIterator的目的是提供很多实用方法。 虽然理论上可以在 trait 中使用不采用 self 的方法,但需要在具体类型(例如 playground)上调用它们,因为实现 trait具体类型可以覆盖它们。 → 我的建议是让它们像 fn&lt;T: Clone&gt; fill1 (elem: T, n: usize) -&gt; RepeatN&lt;T&gt; … 这样独立的通用函数 谢谢。如果您写该评论作为答案,我很乐意接受。 【参考方案1】:

好吧,你还没有为任何类型实现 trait,所以实际上不存在 fill1 函数。

如果您为实现Iterator&lt;Item = char&gt; 的某些类型实现MyIterator,例如std::iter::Empty&lt;char&gt;,那么您将能够通过该类型调用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) - 关联启动: 关联指定的文件类型, 关联指定的协议

如何使用具有关联类型的非静态特征对象?

如何关联高阶函数之间定义的泛型类型?

associatedtype关联类型

在与 API 调用关联的函数中:未捕获(承诺中)类型错误:无法读取未定义的属性“包含”

swift protocol(协议) associatedtype关联类型