![](/img/trans.png)
[英]How to pass Rc<RefCell<dyn T>> to fn that wants &dyn T?
[英]How to downcast Rc<RefCell<dyn io::Write>> into a concrete type?
我想制作一个结构,文本 output 可以显示在控制台上或存储在内部缓冲区中。 如果文本被缓冲,那么我需要一种返回文本内容的方法。
为此,我使用了一个名为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>`
正如@SvenMarnach 在评论中所写,根据io::Write
编写自定义特征可能是一种解决方案
use std::rc::Rc;
use std::cell::RefCell;
use std::io::{self, Stdout};
trait MyWrite: io::Write {
fn get_buffer(&self) -> Option<String>;
}
impl MyWrite for Stdout {
fn get_buffer(&self) -> Option<String> {
None
}
}
impl MyWrite for Vec<u8> {
fn get_buffer(&self) -> Option<String> {
Some(String::from_utf8(self.clone()).unwrap())
}
}
struct A {
// Rc<RefCell<>> is needed in my real code
writer: Rc<RefCell<dyn MyWrite>>,
}
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> {
let writer = self.writer.borrow();
writer.get_buffer()
}
}
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());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.