我正在尝试开发一种批处理系统。在其中,我想使用某种Process
结构,它拥有所有与过程相关的部分。当前实现使用PhantomData
来强制执行类型约束:
pub struct Process<P: Producer<U>, T: Transformer<U, V>, C: Consumer<V>, U,V>
{
producer: P,
transformer: T,
consumer: C,
p1: PhantomData<U>,
p2: PhantomData<V>,
}
我们的想法是Producer
发出的类型将被Transformer
(可能是另一种类型)使用并由Consumer
使用。因此类型必须匹配。
Process
结构应该拥有实现Producer
,Transformer
和Consumer
特征的项目。我认为这就是我需要使用类型参数的原因。因为我不能像
...
producer: Producer<U>,
...
因为编译时的大小未知。
有更好的方法吗?我对Rust很陌生,所以我可能会在错误的方向思考。
解决方案有效,但对于那些PhantomData
字段看起来有些奇怪。也许这只是PhantomData
用于什么?
答案 0 :(得分:8)
您需要关联的类型,而不是类型参数:
trait Producer {
type Output;
fn produce(&self) -> Self::Output;
}
trait Transformer {
type Input;
type Output;
fn transform(&self, val: Self::Input) -> Self::Output;
}
trait Consumer {
type Input;
fn consume(&self, val: Self::Input);
}
struct Process<P, T, C>
where P: Producer,
T: Transformer<Input = P::Output>,
C: Consumer<Input = T::Output>
{
producer: P,
transformer: T,
consumer: C,
}
impl<P, T, C> Process<P, T, C>
where P: Producer,
T: Transformer<Input = P::Output>,
C: Consumer<Input = T::Output>
{
fn run(&self) {
let a = self.producer.produce();
let b = self.transformer.transform(a);
self.consumer.consume(b);
}
}
struct MakeNum;
impl Producer for MakeNum {
type Output = u8;
fn produce(&self) -> u8 { 41 }
}
struct AddOne;
impl Transformer for AddOne {
type Input = u8;
type Output = u8;
fn transform(&self, val: u8) -> u8 { val + 1 }
}
struct PrintNum;
impl Consumer for PrintNum {
type Input = u8;
fn consume(&self, val: u8) { println!("Value was {}", val) }
}
fn main() {
let process = Process {
producer: MakeNum,
transformer: AddOne,
consumer: PrintNum,
};
process.run();
}
虽然我通常不会在where
上添加struct
条款,但我只能在impl
上使用new
方法这也确保了约束。