如何使用泛型方法实现特征?

Posted

技术标签:

【中文标题】如何使用泛型方法实现特征?【英文标题】:How do I implement a trait with a generic method? 【发布时间】:2019-04-04 17:34:45 【问题描述】:

我正在尝试实现一个包含通用方法的特征。

trait Trait 
    fn method<T>(&self) -> T;


struct Struct;

impl Trait for Struct 
    fn method(&self) -> u8 
        return 16u8;
    

我明白了:

error[E0049]: method `method` has 0 type parameters but its trait declaration has 1 type parameter
 --> src/lib.rs:8:5
  |
2 |     fn method<T>(&self) -> T;
  |     ------------------------- expected 1 type parameter
...
8 |     fn method(&self) -> u8 
  |     ^^^^^^^^^^^^^^^^^^^^^^ found 0 type parameters

我应该如何正确编写impl 块?

【问题讨论】:

【参考方案1】:

函数和方法中的类型参数是通用的。这意味着对于所有 trait 实现者,Trait::method&lt;T&gt; 必须为任何 T 实现,其约束与 trait 所指示的约束完全相同(在这种情况下,T 上的约束只是隐含的 Sized)。

您指出的编译器错误消息表明它仍然需要参数类型T。相反,您的Struct 实现假设T = u8,这是不正确的。类型参数由方法的调用者而不是实现者决定,因此T 可能并不总是u8

如果您希望让实现者选择特定类型,则必须改为在关联类型中具体化。

trait Trait 
    type Output;

    fn method(&self) -> Self::Output;


struct Struct;

impl Trait for Struct 
    type Output = u8;

    fn method(&self) -> u8 
        16
    

另请阅读Rust 编程语言的这一部分:Specifying placeholder types in trait definitions with associated types。

另见:

"Expected type parameter" error in the constructor of a generic struct When is it appropriate to use an associated type versus a generic type?

【讨论】:

谢谢,这对我有帮助。我想知道是否可以限制具有特征的类型,例如type Output impl CustomOutput?这就是你所说的泛型关联类型吗?我看到这个 github 的跟踪问题,所以我想知道这是否不可能。【参考方案2】:

除了使用关联类型的方法,从this answer,您还可以将泛型添加到特征中。

trait Trait<T> 
    fn method(&self) -> T;


impl Trait<u8> for Struct 
    fn method(&self) -> u8 
        16
    

当只有一种逻辑形式可供使用时,您使用“关联类型”方式。当有多个有意义的输出类型时,您可以使用通用特征,例如这是合法的:

struct Struct;

trait Trait<T> 
    fn method(&self) -> T;


impl Trait<u8> for Struct 
    fn method(&self) -> u8 
        16
    


impl Trait<String> for Struct 
    fn method(&self) -> String 
        "hello".to_string()
    


fn main() 
    let s = Struct;
    let a: u8 = s.method();
    let b: String = s.method();
    println!("a=, b=", a, b);

据我所知,你不能使用基于关联类型的特征来做到这一点。

【讨论】:

以上是关于如何使用泛型方法实现特征?的主要内容,如果未能解决你的问题,请参考以下文章

方法存在但不满足以下特征界限(泛型)

理解C#泛型运作原理

如何使用 JPA/hibernate EntityManager 和 EJB3.0 实现泛型?

十分钟深刻理解 Java高级——泛型

Java泛型详解

使用多种泛型类型在 Java 中实现抽象泛型方法