我试图做一个简单的模板引擎(用于发送具有不同内容的消息),但遇到了一个问题,我不能使“虚拟”方法参数化。
trait Evaluatable {
fn evaluate(&self, dest: &mut impl std::io::Write);
}
struct A {}
struct B {}
impl Evaluatable for A {
fn evaluate(&self, dest: &mut impl std::io::Write) {
dest.write(b"value from A");
}
}
impl Evaluatable for B {
fn evaluate(&self, dest: &mut impl std::io::Write) {
dest.write(b"value from B");
}
}
struct Expression {
values: Vec<Box<dyn Evaluatable>>
}
impl Expression {
fn evaluate(&self, dest: &mut impl std::io::Write) {
self.values.iter().for_each(|e| e.evaluate(dest))
}
}
fn test() -> std::io::Result<()> {
let expr = Expression { values: vec![Box::new(A{}), Box::new(B{})]};
//Write to a file:
let file = std::io::BufWriter::new(std::fs::File::create_new("afile")?);
expr.evaluate(&mut file);
//Write to the memory
let data = Vec::new();
expr.evaluate(&mut data);
Ok(())
}
我知道这是因为对象的安全性等,但如何实现这一点呢?可以建议使Write也成为一个dyn对象,并传递Write as**&mut dyn Write**,但调用一个虚方法为每个字节写不是我所希望的。什么是常见的方法来解决这个问题?
1条答案
按热度按时间qvk1mo1f1#
你可以使用一个保存trait对象的BufWriter,这会延迟对flushes的虚调用。
如果你必须用
BufWriter
做其他事情,这是不方便的,因为它现在有一个附加的生命周期,所以可能不适用于所有情况。其中一些可以通过使用BufWriter<Box<dyn Write>>
来修复,但这是一个额外的分配。这也意味着使用不同类型的缓冲写入器的调用者必须将它 Package 在另一个缓冲区中。