使用具有特征的泛型
Using generics with trait
我正在尝试实现包含通用函数的特征。但是,我无法在已实现的函数中实例化结构。
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
}
}
}
当尝试在已实现的函数中实例化 Pass
结构时,编译器抱怨参数应为 extractor
字段的类型:
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`
您的 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")
但是,您正在构建比 get_pass
中的通用 Pass<E>
更具体的内容:一个 Pass<BooksExtractor>
!如果允许的话,那就意味着我写的代码不会像我预期的那样工作。
您的 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
}
}
}
简而言之,当 caller 可以选择函数返回的类型时,您应该使用泛型,当 implementer[=21] 时,您应该使用关联类型=]选择类型。
另见 。
我正在尝试实现包含通用函数的特征。但是,我无法在已实现的函数中实例化结构。
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
}
}
}
当尝试在已实现的函数中实例化 Pass
结构时,编译器抱怨参数应为 extractor
字段的类型:
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`
您的 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")
但是,您正在构建比 get_pass
中的通用 Pass<E>
更具体的内容:一个 Pass<BooksExtractor>
!如果允许的话,那就意味着我写的代码不会像我预期的那样工作。
您的 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
}
}
}
简而言之,当 caller 可以选择函数返回的类型时,您应该使用泛型,当 implementer[=21] 时,您应该使用关联类型=]选择类型。
另见