如何使用泛型方法实现特征?
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<T>
必须为任何 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);
据我所知,你不能使用基于关联类型的特征来做到这一点。
【讨论】:
以上是关于如何使用泛型方法实现特征?的主要内容,如果未能解决你的问题,请参考以下文章