当前位置: 首页 > 知识库问答 >
问题:

特征的泛型类型和泛型关联类型有什么区别?

葛书
2023-03-14

这个问题是在泛型关联类型在Rust中可用之前提出的,尽管它们是被提出和开发的。

我的理解是,特征泛型和关联类型在它们可以绑定到结构的类型数量上有所不同。

struct Struct;

trait Generic<G> {
    fn generic(&self, generic: G);
}

impl<G> Generic<G> for Struct {
    fn generic(&self, _: G) {}
}

fn main() {
    Struct.generic(1);
    Struct.generic("a");
}

关联类型仅绑定1个类型:

struct Struct;

trait Associated {
    type Associated;

    fn associated(&self, associated: Self::Associated);
}

impl Associated for Struct {
    type Associated = u32;

    fn associated(&self, _: Self::Associated) {}
}

fn main() {
    Struct.associated(1);
    // Struct.associated("a"); // `expected u32, found reference`
}

泛型关联类型是这两种类型的混合。它们绑定到一个类型,正好有一个关联的生成器,而生成器又可以关联任何数量的类型。那么前面示例中的generic和这个泛型关联类型有什么区别呢?

struct Struct;

trait GenericAssociated {
    type GenericAssociated;

    fn associated(&self, associated: Self::GenericAssociated);
}

impl<G> GenericAssociated for Struct {
    type GenericAssociated = G;

    fn associated(&self, _: Self::GenericAssociated) {}
}

共有1个答案

邹英光
2023-03-14

我们再来看看你最后一个例子(被我缩短了):

trait GenericAssociated {
    type GenericAssociated;
}

impl<G> GenericAssociated for Struct {
    type GenericAssociated = G;
}

这不具有泛型关联类型的特性!您只是在impl块上有一个泛型类型,您将该泛型类型分配给关联的类型。嗯,好吧,我知道混乱是从哪里来的了。

您的示例错误为“类型参数g不受impl特征、self类型或谓词的约束”。当《服贸总协定》实施时,这一点不会改变,因为,再一次,这与《服贸总协定》无关。

trait Associated {
    type Associated<T>; // <-- note the `<T>`! The type itself is 
                        //     generic over another type!

    // Here we can use our GAT with different concrete types 
    fn user_choosen<X>(&self, v: X) -> Self::Associated<X>;
    fn fixed(&self, b: bool) -> Self::Associated<bool>;
}

impl Associated for Struct {
    // When assigning a type, we can use that generic parameter `T`. So in fact,
    // we are only assigning a type constructor.
    type Associated<T> = Option<T>;

    fn user_choosen<X>(&self, v: X) -> Self::Associated<X> {
        Some(x)
    }
    fn fixed(&self, b: bool) -> Self::Associated<bool> {
        Some(b)
    }
}

fn main() {
    Struct.user_choosen(1);    // results in `Option<i32>`
    Struct.user_choosen("a");  // results in `Option<&str>`
    Struct.fixed(true);        // results in `Option<bool>`
    Struct.fixed(1);           // error
}

流式迭代器的GAT版本如下所示:

trait Iterator {
    type Item<'a>;
    fn next(&self) -> Option<Self::Item<'_>>;
}

在current Rust中,我们可以将lifetime参数放在trait上,而不是相关的类型:

trait Iterator<'a> {
    type Item;
    fn next(&'a self) -> Option<Self::Item>;
}

到目前为止还不错:所有迭代器都可以像以前一样实现这个特性。但如果我们要用呢?

fn count<I: Iterator<'???>>(it: I) -> usize {
    let mut count = 0;
    while let Some(_) = it.next() {
        count += 1;
    }
    count
}
    null
fn count<I: Iterator>(it: I) { ... }

它会奏效的。因为“具体生存期的应用”只有在我们调用next时才会发生。

如果您对更多信息感兴趣,可以看看我的博客文章“在没有GATS的情况下解决Generalized Streaming Iterator Problem”,我尝试在traits上使用泛型类型来解决GATS的不足。而且(剧透):通常都不起作用。

 类似资料:
  • 类型和泛型 类型系统的首要目的是检测程序错误。类型系统有效的提供了一个静态检测的有限形式,允许我们代码中明确某种类型的变量并且编译器可以验证。类型系统当然也提供了其他好处,但错误检测是他存在的理由(Raison d’Être) 我们使用类型系统应当反映这一目标,但我们必须考虑到读者(译注:读你代码的人):明智地使用类型可以增加清晰度,而过份聪明只会迷乱。 Scala的强大类型系统是学术探索和实践共

  • 如何获取这个类的类型?对于上下文,我使用ModelMapper,我需要类类型T从S转换为T。 背景: 我已经尝试了N种方法,其中我放置了“//一些方法来获取类型”,但没有任何效果。例如: 或

  • null 在编写代码时,什么时候应该选择关联类型而不是泛型类型参数,什么时候应该做相反的操作?

  • 在研究泛型时,我注意到泛型方法和泛型类型(类或接口)在类型引入语法上的一个差异使我感到困惑。 泛型方法的语法为 文件上说 为了彼此保持一致,我希望方法语法为 ,或者类型语法(for class)为,但事实显然并非如此。 为什么一个要介绍在前,另一个要介绍在后? 我主要以的形式使用泛型,并认为可能看起来很奇怪,但这是一个主观的参数,此外对于方法也是这样。您可以调用,类似于 在寻找技术解释时,我想在指

  • 泛型类型 除了反省函数, Swift允许你定义自己的泛型类型. 它们是可以用于任意类型的自定义类、结构体、枚举, 和Array、Dictionary方式类型. 1. 定义泛型类型 定义一个普通的结构体 struct IntStack { var items = [Int]() mutating func push(_ item: Int) { items.appen

  • 我是Spring的新手,我正在尝试自动连接一个通用DAO。不幸的是,我遇到了一个错误。我试图根据它搜索信息,但大多数解决方案都声明使用@Qualifier注释,我认为这与我想要实现的目标背道而驰。 所以下面的一些代码(我将摆脱类参数,一旦我处理当前问题): 道 服务 和下面抛出的错误: