如何在 Rust 中将变量设置为泛型类型 Trait 的实现?
我是 Rust 新手,我正在尝试编写一个应用程序,该应用程序基本上使用许多可能的服务之一来获取一些数据,转换它并保存到我的数据库中。
我正在尝试做一些类似 Java 通用接口的事情,根据命令行输入实例化正确的服务并在整个程序中使用它。
我编写了类似这样的代码:
use anyhow::Result;
pub trait Service<T> {
fn get_values(&self, id: u64) -> T;
fn convert_data(&self, input: T, output: &mut Vec<MyDataStruct>) -> Result<String>;
}
以及两种不同的实现:
struct ServiceA {
clientA: DataRetrieverForA,
}
struct ServiceB {
clientB: DataRetrieverForB,
}
impl Service<Result<ADataStruct>> for ServiceA {
fn get_values(&self, id: u64) -> Result<ADataStruct>;
fn convert_data(&self, input: Result<ADataStruct>, output: &mut Vec<MyDataStruct>) -> Result<String>;
}
impl Service<BDataStruct> for ServiceB {
fn get_values(&self, id: u64) -> BDataStruct;
fn convert_data(&self, input: BDataStruct, output: &mut Vec<MyDataStruct>) -> Result<String>;
}
self.get_values(id)
使用self.clientX
检索数据和self.convert_data(input , &mut output)
将数据从 ADataStruct
和 BDataStruct
转换为 MyDataStruct
,然后再将其保存到我的数据库中。
该应用程序将使用 ServiceA
或 ServiceB
运行,具体取决于命令行输入:
fn main() {
// ...
let service: Box<&(dyn Service<_>)> = match cli_service {
Service::A => { Box::new(&ServiceA::new(...) }
Service::B => { Box::new(&ServiceB::new(...) }
};
//...
}
我尝试了很多更改,主要基于 https://doc.rust-lang.org/book/ch10-02-traits.html 和 https://doc.rust-lang.org/book/ch17- 02-trait-objects.html 但我找不到处理使用特征定义中的泛型类型的函数的示例。当我删除通用 参数并将其固定为一些通用结构以进行测试时,代码编译并运行时没有错误。所以我的猜测是我的错误在于通用/特征的使用。
我用这段代码得到的错误:
error[E0277]: the trait bound `ServiceB: Service<ADataStruct>` is not satisfied
--> ori-runner\src\main.rs:40:37
|
40 | ... { Box::new(&ServiceB::new(params)...
| -------- ^^^^^^^^^^^^^^^^^^^^^^ the trait `Service<ADataStruct>` is not implemented for `ServiceB`
| |
| required by a bound introduced by this call
|
= help: the following implementations were found:
<ServiceB as Service<BDataStructure>>
= note: required for the cast to the object type `dyn Service<ADataStruct>>`
我做错了什么?很明显,第一个匹配类型是定义 dyn Service 变量的“_”,但我没有想法和谷歌搜索......
谢谢!
I am new to rust and I am trying to write an app that basically uses one of many possible services to fetch some data, transform it and save to my database.
I am trying to do something like a generic interface from Java, to instantiate the correct service based on command line input and use it throughout the program.
I have coded something like this:
use anyhow::Result;
pub trait Service<T> {
fn get_values(&self, id: u64) -> T;
fn convert_data(&self, input: T, output: &mut Vec<MyDataStruct>) -> Result<String>;
}
and two different implementations:
struct ServiceA {
clientA: DataRetrieverForA,
}
struct ServiceB {
clientB: DataRetrieverForB,
}
impl Service<Result<ADataStruct>> for ServiceA {
fn get_values(&self, id: u64) -> Result<ADataStruct>;
fn convert_data(&self, input: Result<ADataStruct>, output: &mut Vec<MyDataStruct>) -> Result<String>;
}
impl Service<BDataStruct> for ServiceB {
fn get_values(&self, id: u64) -> BDataStruct;
fn convert_data(&self, input: BDataStruct, output: &mut Vec<MyDataStruct>) -> Result<String>;
}
the self.get_values(id)
uses the self.clientX
to retrieve data and self.convert_data(input, &mut output)
transforms data from ADataStruct
and BDataStruct
to MyDataStruct
before saving it to my database.
The app will run using either ServiceA
or ServiceB
depending on command line input:
fn main() {
// ...
let service: Box<&(dyn Service<_>)> = match cli_service {
Service::A => { Box::new(&ServiceA::new(...) }
Service::B => { Box::new(&ServiceB::new(...) }
};
//...
}
I have tried many changes, mostly based on https://doc.rust-lang.org/book/ch10-02-traits.html and https://doc.rust-lang.org/book/ch17-02-trait-objects.html but I can't find an example that handles functions that use a generic type from trait definition. When I removed the generic parameter and fixed it to some common struct for testing, the code compiled and ran with no errors. So my guess is my mistake is with generic/trait usage.
The error I get with this code:
error[E0277]: the trait bound `ServiceB: Service<ADataStruct>` is not satisfied
--> ori-runner\src\main.rs:40:37
|
40 | ... { Box::new(&ServiceB::new(params)...
| -------- ^^^^^^^^^^^^^^^^^^^^^^ the trait `Service<ADataStruct>` is not implemented for `ServiceB`
| |
| required by a bound introduced by this call
|
= help: the following implementations were found:
<ServiceB as Service<BDataStructure>>
= note: required for the cast to the object type `dyn Service<ADataStruct>>`
What am I doing wrong? It is obvious the first match type is defining the '_' of the dyn Service variable, but I am out of ideas and google searches...
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于类型不同,一种选择是将它们包装在枚举中,并使用一些方法来根据决策计算所需的任何内容。枚举包装器将抽象服务操作。
游乐场
Since the types are different, one option would be to wrap them in an
enum
and have some method/s for computing whatever needed depending on the decision. The enum wrapper would abstract the services operations.Playground