【发布时间】:2021-02-28 02:49:23
【问题描述】:
我是 Rust 的新手,我在使用“特征对象”时遇到了问题...
现在,我有 App 结构和 panels 字段,它是实现 Panel 特征的 WavePanel 结构的 Vec。
因为我有更多的实现 Panel,所以我希望 panels 变得更通用。
所以,我尝试将Panel 指定为该字段的特征对象,但它不起作用....
这是它目前的样子(更改前):
use crate::panels::wave::WavePanel;
use crate::panels::Panel;
#[derive(Clone, Debug)]
pub struct App {
points: Vec<Point>,
points_prev: Vec<Point>,
panels: Vec<WavePanel>, // <-- `WavePanel` struct works just fine.
}
impl App {
pub fn new(config: &Config) -> Result<Self, String> {
let color: String = config.color.clone();
let color2: String = config.color2.clone();
let mut panels = vec![];
for panel in &config.panels {
let id = panel.id.clone();
match id.as_str() {
"wave" => {
panels.push(WavePanel::new(
id.as_str(),
color.as_str(),
color2.as_str(),
)?);
}
_ => {}
}
}
Ok(App {
points: vec![],
points_prev: vec![],
panels: panels,
})
}
}
这是Panel 特征:
pub trait Panel<G: Graphics> {
fn g(&self) -> Rc<RefCell<G>>;
fn reset(&mut self) {
if let Ok(mut g) = self.g().try_borrow_mut() {
let (width, height) = g.size();
g.reset(width, height);
};
}
}
这就是WavePanel 实现Panel trait 的方式:
#[derive(Clone, Debug)]
pub struct WavePanel {
id: String,
g: Rc<RefCell<WaveGraphics>>,
graph_type: Rc<Cell<GraphType>>,
}
impl Panel<WaveGraphics> for WavePanel {
fn g(&self) -> Rc<RefCell<WaveGraphics>> {
self.g.clone()
}
}
而且,这是我尝试过的(之后):
use crate::panels::wave::WavePanel;
use crate::panels::Panel;
#[derive(Clone, Debug)]
pub struct App {
points: Vec<Point>,
points_prev: Vec<Point>,
panels: Vec<Box<dyn Panel>>, // <-- This does not work...
}
impl App {
pub fn new(config: &Config) -> Result<Self, String> {
let color: String = config.color.clone();
let color2: String = config.color2.clone();
let mut panels = vec![];
for panel in &config.panels {
let id = panel.id.clone();
match id.as_str() {
"wave" => {
// Pushing it into Box this time.
panels.push(Box::new(
WavePanel::new(
id.as_str(),
color.as_str(),
color2.as_str(),
)?
));
}
_ => {}
}
}
Ok(App {
points: vec![],
points_prev: vec![],
panels: panels,
})
}
}
这是错误:
error[E0107]: wrong number of type arguments: expected 1, found 0
--> src/app.rs:15:25
|
15 | panels: Vec<Box<dyn Panel>>,
| ^^^^^ expected 1 type argument
error: aborting due to previous error
For more information about this error, try `rustc --explain E0107`.
error: could not compile `perlin-wave`
Box<dyn Panel> 不应该足够明确吗?
尝试了很多东西,但仍然没有运气...
拜托,我非常需要你的帮助......
编辑:已解决 (2021.3.4)
对于 trait 对象的错误使用,kmdreko 是对的。我拥有的特质不是Panel,而是Panel<G: Graphics>,它们完全不同。
正如 kmdreko 所提到的,我停止将 G 喂给 Panel 特征,并将 G 替换为 dyn Graphics(对于字段 g),这就成功了!
它解决了最初的错误。
但是,出现了另一个问题...
当我实际上将派生Panel 特征的结构WavePanel 推送到panels: Vec<Box<dyn Panel>> 时,我收到错误消息:expected trait object "dyn Panel", found struct "WavePanel"。这是实现异构vec的问题,不是kmdreko的错。就最初关心的问题而言,kmdreko 的答案应该是正确的答案。
为此,我在here找到了解释。
所以,这是关于 Rust 在本地推断 WavePanel 结构而不是 dyn Panel trailt 对象。就在我创建 Box::new(WavePanel::new(..)) 时,现在我明确告诉我我想要 trait 对象 Vec<Box<dyn Panel>>,并且它修复了它。
还有一个问题....
由于它与主题有关,我认为也值得留个便条...
所以,我在Panel 中有字段g 现在在Panel 中有dyn Graphics 而不是G。 Graphics trait 现在也发生了类似的情况。就像我对 Panel 特征有 WavePanel 结构一样,我对 Graphics 特征有 WaveGraphics 结构。在某种程度上,Rust 现在与在Panel 中定义的g 字段的类型混淆了...对于这个问题,我决定为Graphics 特征派生Any 特征。只要我在Graphics trait 中定义as_any_mut() 总是返回Any struct,当我真正想使用它时,例如g.draw(),我总是可以将trait 对象转换为Any,然后做这个:g.as_any_mut().downcast_mut::<WaveGraphics>() 。
对于最终差异(对于所有修复),请找到 here。
【问题讨论】: