【发布时间】:2020-08-20 08:42:41
【问题描述】:
我想创建一个结构,它的文本输出既可以显示在控制台上,也可以存储在内部缓冲区中。如果文本被缓冲,那么我需要一个返回文本内容的方法。
为此,我使用了一个名为writer 的属性,即dyn std::io::Write(包装到Rc<RefCell<>> 中,因为我的真实代码需要它)。然后在结构构造中,我为此属性创建一个io::stdout() 实例或Vec::<u8>::new() 实例。
use std::rc::Rc;
use std::cell::RefCell;
use std::io;
struct A {
// Rc<RefCell<>> is needed in my real code
writer: Rc<RefCell<dyn io::Write>>,
}
impl A {
pub fn new() -> Self {
Self { writer: Rc::new(RefCell::new(io::stdout())) }
}
pub fn new_buffered() -> Self {
Self { writer: Rc::new(RefCell::new(Vec::<u8>::new())) }
}
pub fn write(&self, s: &str) {
let mut writer = self.writer.borrow_mut();
writeln!(writer, "{}", s).unwrap();
}
/// Returns None if the struct is not buffered, otherwise a copy of the buffered output.
pub fn get_buffer(&self) -> Option<String> {
match GET_VEC_U8() { // <- Unable to implement this line
Some(vec_u8) => {
Some(String::from_utf8(vec_u8.clone()).unwrap())
},
None => None,
}
}
}
fn main() {
let a = A::new();
a.write("foo");
println!("Buffer: {:?}", a.get_buffer());
let b = A::new_buffered();
b.write("bar");
println!("Buffer: {:?}", b.get_buffer());
}
问题
但是当作者是Vec<u8>时,我不知道如何提取文本内容(方法get_buffer())。我该怎么做?
我的尝试
我试图将属性包装成Box:
struct A {
writer: Rc<RefCell<Box<dyn io::Write>>>,
}
然后在上面使用Box::downcast():
impl A {
pub fn get_buffer(&self) -> Option<String> {
let writer = self.writer.borrow();
match (*writer).downcast::<Vec<u8>>() {
Ok(vec_u8) => Some(String::from_utf8(vec_u8.clone()).unwrap()),
Err(_) => None,
}
}
}
但我收到此错误:
error[E0599]: no method named `downcast` found for struct `std::boxed::Box<dyn std::io::Write>` in the current scope
--> src/main.rs:27:25
|
27 | match (*writer).downcast::<Vec<u8>>() {
| ^^^^^^^^ method not found in `std::boxed::Box<dyn std::io::Write>`
【问题讨论】:
-
Box上的向下转换方法仅适用于Box<dyn Any + 'static>。你在这里有一个Box<dyn Writer>,所以你不能沮丧。将其更改为Box<dyn Writer + Any + 'static>之类的内容无济于事,因为它与Box<dyn Any + 'static>的类型不同,因此您仍然无法使用downcast()方法。 -
您的选择是使用枚举而不是动态调度,或者根据
Writer使用额外的get_buffer()方法实现自定义特征。对于Vec<u8>和StdOut都可以轻松实现此方法。 -
@SvenMarnach 是的,我已经尝试添加
'static,确实还是不行。 -
@SvenMarnach 谢谢,您建议的自定义特征解决方案按预期工作
标签: rust dynamic-typing