我正在尝试实现一个返回Service具有关联类型的工厂方法。我让它在没有关联类型的情况下工作,但是一旦我添加了它,无论我如何按摩它,我都无法编译它..
这是Service:
trait QType {}
trait Service {
type Query: QType;
fn sanitize(&self, query: &str) -> Result<Self::Query, String>;
fn run(&self, query: &Self::Query) -> Result<(), String>;
}
Run Code Online (Sandbox Code Playgroud)
所以想法是sanitize函数返回 的一个实例Query,然后可以将其传递给run函数。
工厂看起来像这样(不编译):
fn factory<Q: QType>(name: &str) -> Box<dyn Service<Query = Q>> {
match name {
"amazon" => Box::new(amzn::Amazon {}),
other => panic!("Invalid service {}", other),
}
}
Run Code Online (Sandbox Code Playgroud)
现在我这里只有一个服务,我可以在签名中的类型参数中进行特定——这将使它编译——但我想要一个通用的工厂方法并添加更多服务。
下面是Amazon服务的实现:
mod amzn {
use super::*;
pub struct Amazon {}
pub struct Product {
name: String,
}
impl QType for Product {}
impl Service for Amazon {
type Query = Product;
fn sanitize(&self, query: &str) -> Result<Product, String> {}
fn run(&self, query: &Product) -> Result<(), String> {}
}
}
Run Code Online (Sandbox Code Playgroud)
编译器说:
错误[E0271]:类型不匹配解决`::Query == Q`
--> src/main.rs:9:21
|
9 | “亚马逊” => Box::new(amzn::Amazon {}),
| ^^^^^^^^^^^^^^^^^^^^^^^^^ 预期类型参数,找到结构`amzn::Product`
|
= 注意:预期类型`Q`
找到类型`amzn::Product`
= help: 必须约束类型参数以匹配其他类型
= 注意:有关更多信息,请访问 https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
= 注意:需要转换为对象类型 `dyn Service`
基于此错误消息,我不确定如何指定类型参数。我曾尝试提取创建Amazon并为其提供显式类型参数,但这只会导致不同的错误。此外,遵循书中链接的第 10.02 章没有对关联类型的情况进行任何解释。最后,我还尝试了RFC-1598: Generic Associated Types的路线,但我既无法编译它,也不确定我是否真的需要它。
另请注意,我在 SO 上围绕类似问题添加了基于其他答案的Box包装器和QType限制,但我在这里可能完全走错了路。
任何帮助深表感谢。
此签名无法实现:
fn factory<Q: QType>(name: &str) -> Box<dyn Service<Query = Q>>
Run Code Online (Sandbox Code Playgroud)
关联类型始终由实现类型唯一确定。即每个实现Service只选择一个关联类型Query。
这与 不一致factory,后者让调用者决定关联的类型应该是什么。应该很清楚地看到,如果您factory使用Qnot调用,则表达式中Product的代码match不再进行类型检查。
您可以通过修复以下选项来完成这项工作Query:
fn factory(name: &str) -> Box<dyn Service<Query = Product>> {
match name {
"amazon" => Box::new(amzn::Amazon {}),
other => panic!("Invalid service {}", other),
}
}
Run Code Online (Sandbox Code Playgroud)
如果您希望调用者选择类型,那么您需要找到一种方法,以便函数体可以为任何选择的Q. 例如,您可以将构造与QType特征相关联:
trait QType {
fn create_service(name: &str) -> Option<Box<dyn Service<Query = Self>>>;
}
fn factory<Q: QType>(name: &str) -> Box<dyn Service<Query = Q>> {
Q::create_service(name).expect("Invalid service")
}
Run Code Online (Sandbox Code Playgroud)
并为您的类型实施:
impl QType for Product {
fn create_service(name: &str) -> Option<Box<dyn Service<Query = Self>>> {
match name {
"amazon" => Some(Box::new(amzn::Amazon {})),
other => None,
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
236 次 |
| 最近记录: |