【问题标题】:Rust: defining trait for generic function that compares lengthRust:为比较长度的通用函数定义特征
【发布时间】:2014-12-15 05:09:01
【问题描述】:

所以我想写一个这样的函数:

fn is_longer_than<T>(thing: T, threshold: int) -> bool {
    thing.len() > threshold 
}

一般来说,我对 rust 和静态类型/泛型还很陌生,但据我了解,您需要使用一个特征来约束 T,在这种情况下,实现方法 len

我试图做这样的事情:

trait HasLength {
    fn len(&self) -> int
}

fn is_longer_than<T>(thing: HasLength, threshold: int) -> bool {
    thing.len() > threshold 
}

但这不起作用。我错过了什么?我猜有一个涵盖这种情况的预定义特征?即便如此,有没有办法定义它(为了学习)

【问题讨论】:

    标签: generics rust


    【解决方案1】:

    您确实需要将T 限制为特征HasLength,这是通过&lt;T: HasLength&gt; 之类的语法完成的。

    trait HasLength {
        fn len(&self) -> int;
    }
    
    fn is_longer_than<T: HasLength>(thing: T, threshold: int) -> bool {
        thing.len() > threshold 
    }
    

    这声明函数is_longer_than 采用具有HasLength 实现的任何类型T。请注意,您必须为您可能想要传递给is_longer_than 的每种类型定义一个实现(使用impl)。

    或者,函数可以定义为:

    fn is_longer_than2(thing: &HasLength, threshold: int) -> bool {
        thing.len() > threshold 
    }
    

    这声明了一个接受 trait 对象 的函数,该对象将包括对数据的引用和对 trait 的动态调度表的引用。您仍然需要定义适当的impl 才能创建特征对象。

    这两种形式的区别在于第一种形式将专门用于每种类型,也就是说,将为与函数一起使用的每种类型编译不同版本的函数。第二种形式更像是Java等语言中的OO-code——只会编译一个版本的函数,但是这个版本必须使用动态调度表来调用len

    以下是 HasLength 特征的示例 impl,它将 i32 的长度定义为表示它所需的 base-10 位数:

    impl HasLength for i32 {
      fn len(&self) -> int { self.to_string().len() as int }
    }
    

    【讨论】:

    • 你能解释一下impl在这种情况下的定义吗?我一直在阅读指南,我看到 impl 如何使用手动和任意定义的方法,但我不明白如何将它与标准库已经定义的 len() 连接起来。
    • @AllTheTime 根据已经存在的方法创建特征可能是一个不同的问题。我不确定这是否可能。
    • @AllTheTime 听起来你想要结构类型(又名鸭子类型) - 一种引用定义方法 len 的所有类型的方法。这在 Rust 中是不可能的。但是,请参阅我的新编辑示例impl
    • @AllTheTime:你可以手动实现trait来调用固有方法:is.gd/Qd5eVt
    • @Shepmaster:有可能,这要归功于统一函数调用语法 (UFCS):is.gd/Qd5eVt
    猜你喜欢
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    • 2014-02-04
    • 2018-08-31
    • 1970-01-01
    • 1970-01-01
    • 2016-10-05
    • 2022-08-22
    相关资源
    最近更新 更多