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

时间:2018-10-31 14:03:59

标签: rust

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

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块?

2 个答案:

答案 0 :(得分:16)

函数和方法中的

类型参数是通用的。这意味着对于所有特征实现者,必须对Trait::method<T>实施T,且约束必须与特征所指示的约束完全相同(在这种情况下,对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

另请参阅:

答案 1 :(得分: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);
}

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