我正在尝试克隆盒装特征的向量 . 自然地简单地在实现我的特征的所有结构上派生 Clone
并不是在编译时知道实现该特征的所有结构都具有 Clone
.
好吧,所以我接着尝试使用 Clone
作为超级画面,但这只会导致 Headers 中的错误 . 我对解决方案感到茫然 .
这是最小工作实现(或不工作,因为我无法克隆)
#![allow(dead_code, unused_macros)]
use std::fmt::Debug;
trait MusicElement: Debug + Clone {
fn duration(&self) -> f32;
}
#[derive(Debug, Clone)]
struct Note<'a> {
name: &'a str,
duration: f32,
}
impl<'a> MusicElement for Note<'a> {
fn duration(&self) -> f32 {
self.duration
}
}
#[derive(Debug, Clone)]
struct Pause {
duration: f32,
}
impl MusicElement for Pause {
fn duration(&self) -> f32 {
self.duration
}
}
#[derive(Debug, Clone)]
struct Sequence {
elements: Vec<Box<MusicElement>>,
}
impl MusicElement for Sequence {
fn duration(&self) -> f32 {
self.elements.iter().map(|e| e.duration()).sum()
}
}
fn main() {
let a4 = |dur| Box::new(Note { name: "a4", duration: dur });
let seq = Sequence { elements: vec![a4(0.25), a4(0.25), a4(0.5)] };
println!("{:?}", seq);
let seq2 = seq.clone();
println!("{:?}", seq2);
}
出现此错误:
error[E0038]: the trait `MusicElement` cannot be made into an object
--> src/main.rs:33:5
|
33 | elements: Vec<Box<MusicElement>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MusicElement` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
这是一个容易运行的代码link to the playground .
我也试图在 Sequence
Vec<Box<MusicElement + Clone>>
中制作 elements
向量,但这也不起作用 .
我无法在网上找到任何有用的解决方案,所以这是我的问题:如何使代码可以克隆?
2 回答
解决方案在于结合迄今为止的评论中的建议 - @Lukas Kalbertodt's comment中的答案告诉您必须为所有兼容(
'static + MusicElement + Clone
)类型创建一个全面的特征实现 . 实现所需的唯一后续步骤是将Note.name
字段的类型从&'a str
更改为String
,as metioned by @Boiethios:编译,所以它应该足够了!
我的objekt crate提供了jonny's answer的可重用实现 . 有了它,您可以使您的原始代码只需最少的更改即可运行 .
之前:
之后: