我正在尝试实现包含通用函数的特征。但是,我无法在实现的函数中实例化一个结构。
trait Extractor {
fn parse(&self) -> String;
}
struct BooksExtractor {}
impl Extractor for BooksExtractor {
fn parse(&self) -> String {
"test".to_owned()
}
}
struct Pass<E: Extractor> {
pub extractor: Option<E>,
pub name: String,
pub next_pass: Option<Box<Pass<E>>>,
}
trait Robot: Sized {
fn get_pass<E: Extractor>(&self) -> Pass<E>;
}
struct GutenbergRobot {}
impl Robot for GutenbergRobot {
fn get_pass<E: Extractor + ?Sized>(&self) -> Pass<E>
where E: Extractor + Sized {
Pass {
extractor: Some(BooksExtractor {}),
name: "test".to_owned(),
next_pass: None
}
}
}
当尝试实例化已实现函数中的extractor
结构时,编译器抱怨参数应为Pass
字段的类型:
error[E0308]: mismatched types
--> src\main.rs:33:29
|
33 | extractor: Some(BooksExtractor {}),
| ^^^^^^^^^^^^^^^^^ expected type parameter, found struct `BooksExtractor`
|
= note: expected type `E`
found type `BooksExtractor`
答案 0 :(得分:2)
您的Robot::get_pass
函数不应是通用的。相反,您应该使用关联的类型:
trait Robot: Sized {
type Extractor: Extractor;
fn get_pass(&self) -> Pass<Self::Extractor>;
}
impl Robot for GutenbergRobot {
type Extractor = BooksExtractor;
fn get_pass(&self) -> Pass<BooksExtractor> {
Pass {
extractor: Some(BooksExtractor {}),
name: "test".to_owned(),
next_pass: None
}
}
}
简而言之,当调用方可以选择函数返回的类型时,应该使用通用类型;而当 implementer 选择类型时,应该使用相关类型。
>另请参阅this question。
答案 1 :(得分:1)
您对get_pass
的函数签名指定它将构造一个Pass<E>
类型。这意味着它应该在Pass<E: Extractor + Sized>
有效的任何地方工作。
想象一下,除了代码之外,您还具有以下结构:
struct OtherBooksExtractor {}
impl Extractor for OtherBooksExtractor {
fn parse(&self) -> String {
"foobar".to_owned()
}
}
然后,您将期望以下操作基于类型:
fn bla() -> Pass<OtherBookExtractor> {
GutenbergRobot.get_pass()
}
assert_eq!(bla.extractor.parse(), "foobar")
但是,您正在构造比Pass<E>
中的通用get_pass
更具体的东西:Pass<BooksExtractor>
!如果允许的话,这意味着我编写的代码将无法正常工作。