我正在尝试克隆一个装箱特质向量。显然,仅在实现我的特质的所有结构体上简单地派生 Clone
是不够的,因为编译器在编译时不知道实现该特质的所有结构体都有 Clone
。
好吧,然后我试图将 Clone
用作超特质,但这只会导致标题中的错误。我对解决方案感到困惑。
以下是最小工作实现(或不起作用,因为我无法进行克隆)
```rust // Rust code ```#![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`
这里有一个游乐场链接,方便运行代码。
我还尝试将Sequence
中的elements
向量改为Vec<Box<MusicElement + Clone>>
,但那也没有起作用。
我在网上找不到任何有用的解决方案,所以我的问题是:如何使代码可克隆?
Note<'a>
不满足静态生命周期。 - Electric CoffeeString
作为名称? - BoiethiosClone
吗?这个错误是由于Rust编译器在编译时需要知道Clone::clone
的具体返回类型,而使用动态分发的Trait对象Box<MusicElement>
是不可能实现的。点击此处了解更多关于对象安全性违规的信息。 - jonny