Using Trait Object for Struct - ERROR: wrong number of type arguments
Using Trait Object for Struct - ERROR: wrong number of type arguments
我是 Rust 的新手,我在使用“Trait Object”时遇到问题...
目前,我有 App
结构和 panels
字段,它是 WavePanel
结构的 Vec,实现了 Panel
特征。
因为我有更多的实现 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
特征的方式:
#[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)
对于特征对象的错误使用,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的回答应该是正确答案。
为此,我在.
中找到了解释
所以,这是关于 Rust 在本地推断 WavePanel
结构而不是 dyn Panel
trailt 对象。就在我创建 Box::new(WavePanel::new(..))
时,现在我明确地告诉我想要特征对象 Vec<Box<dyn Panel>>
,它修复了它。
还有一个问题....
既然涉及到主题,我觉得也值得留个脚注...
因此,我在 Panel
中的字段 g
现在在 Panel
中具有 dyn Graphics
而不是 G
。 Graphics
特征现在也发生了类似的情况。就像我有 WavePanel
结构用于 Panel
特征一样,我有 WaveGraphics
结构用于 Graphics
特征。在某种程度上,Rust 现在与 Panel
中定义的 g
字段的类型混淆了......对于这个问题,我决定为 Graphics
特征派生 Any
特征。只要我将 as_any_mut()
定义为总是 return Any
struct in Graphics
trait,当我真正想要使用它时,例如 g.draw()
,我可以始终将特征对象转换为 Any
,并执行此操作:g.as_any_mut().downcast_mut::<WaveGraphics>()
.
找到最终差异(针对所有修复)here。
Shouldn't Box<dyn Panel>
be explicit enough?
不,您已将 Panel
定义为通用; Panel<A>
和 Panel<B>
是不同的特征。如果你想Panel
不管图形类型都使用,就不能通用。
如果 g()
只是为了支持 reset()
,您可以删除它:
pub trait Panel {
fn reset(&mut self);
}
impl Panel for WavePanel {
fn reset(&mut self) {
if let Ok(mut g) = self.g.try_borrow_mut() {
let (width, height) = g.size();
g.reset(width, height);
};
}
}
或者如果 g()
仍然需要一般地获取图形对象,也将其设为动态:
pub trait Panel {
fn g(&self) -> Rc<RefCell<dyn Graphics>>;
// ^^^^^^^^^^^^
fn reset(&mut self) {
if let Ok(mut g) = self.g().try_borrow_mut() {
let (width, height) = g.size();
g.reset(width, height);
};
}
}
impl Panel for WavePanel {
fn g(&self) -> Rc<RefCell<dyn Graphics>> {
self.g.clone()
}
}
我是 Rust 的新手,我在使用“Trait Object”时遇到问题...
目前,我有 App
结构和 panels
字段,它是 WavePanel
结构的 Vec,实现了 Panel
特征。
因为我有更多的实现 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
特征的方式:
#[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)
对于特征对象的错误使用,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的回答应该是正确答案。
为此,我在
中找到了解释
所以,这是关于 Rust 在本地推断 WavePanel
结构而不是 dyn Panel
trailt 对象。就在我创建 Box::new(WavePanel::new(..))
时,现在我明确地告诉我想要特征对象 Vec<Box<dyn Panel>>
,它修复了它。
还有一个问题....
既然涉及到主题,我觉得也值得留个脚注...
因此,我在 Panel
中的字段 g
现在在 Panel
中具有 dyn Graphics
而不是 G
。 Graphics
特征现在也发生了类似的情况。就像我有 WavePanel
结构用于 Panel
特征一样,我有 WaveGraphics
结构用于 Graphics
特征。在某种程度上,Rust 现在与 Panel
中定义的 g
字段的类型混淆了......对于这个问题,我决定为 Graphics
特征派生 Any
特征。只要我将 as_any_mut()
定义为总是 return Any
struct in Graphics
trait,当我真正想要使用它时,例如 g.draw()
,我可以始终将特征对象转换为 Any
,并执行此操作:g.as_any_mut().downcast_mut::<WaveGraphics>()
.
找到最终差异(针对所有修复)here。
Shouldn't
Box<dyn Panel>
be explicit enough?
不,您已将 Panel
定义为通用; Panel<A>
和 Panel<B>
是不同的特征。如果你想Panel
不管图形类型都使用,就不能通用。
如果 g()
只是为了支持 reset()
,您可以删除它:
pub trait Panel {
fn reset(&mut self);
}
impl Panel for WavePanel {
fn reset(&mut self) {
if let Ok(mut g) = self.g.try_borrow_mut() {
let (width, height) = g.size();
g.reset(width, height);
};
}
}
或者如果 g()
仍然需要一般地获取图形对象,也将其设为动态:
pub trait Panel {
fn g(&self) -> Rc<RefCell<dyn Graphics>>;
// ^^^^^^^^^^^^
fn reset(&mut self) {
if let Ok(mut g) = self.g().try_borrow_mut() {
let (width, height) = g.size();
g.reset(width, height);
};
}
}
impl Panel for WavePanel {
fn g(&self) -> Rc<RefCell<dyn Graphics>> {
self.g.clone()
}
}