不能克隆 Vec<Box<Trait>> 因为 Trait 不能变成 object
Can't clone Vec<Box<Trait>> because Trait cannot be made into an object
我正在尝试克隆盒装特征的载体。
自然地简单地在实现我的特征的所有结构上推导 Clone
是不够的,因为编译器在编译时不知道所有实现特征的结构都具有 Clone
.
好的,所以我随后尝试使用 Clone
作为超级特征,但这只会导致标题中的错误。我不知所措。
这是最小的工作实现(或者不工作,因为我不能克隆)
#![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
中的 elements
向量变成 Vec<Box<MusicElement + Clone>>
,但那也没用。
我无法在网上找到任何有用的解决方案,所以这是我的问题:如何使代码可克隆?
解决方案在于结合目前评论中的建议 - tells you that you must create a blanket trait implementation for all compatible ('static + MusicElement + Clone
) types. The only subsequent step necessary for your implementation is changing the Note.name
field's type from &'a str
to String
, 中的答案:
#![allow(dead_code, unused_macros)]
use std::fmt::Debug;
trait MusicElement: MusicElementClone + Debug {
fn duration(&self) -> f32;
}
trait MusicElementClone {
fn clone_box(&self) -> Box<MusicElement>;
}
impl<T: 'static + MusicElement + Clone> MusicElementClone for T {
fn clone_box(&self) -> Box<MusicElement> {
Box::new(self.clone())
}
}
impl Clone for Box<MusicElement> {
fn clone(&self) -> Box<MusicElement> {
self.clone_box()
}
}
#[derive(Debug, Clone)]
struct Note {
name: String,
duration: f32,
}
impl MusicElement for Note {
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: String::from("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);
}
编译通过,所以应该足够了!
我的objekt
crate provides a reusable implementation of 。有了它,您只需进行最少的更改即可使您的原始代码正常工作。
之前:
trait MusicElement: Debug + Clone {
fn duration(&self) -> f32;
}
之后:
#[macro_use]
extern crate objekt;
trait MusicElement: Debug + objekt::Clone {
fn duration(&self) -> f32;
}
clone_trait_object!(MusicElement);
// Everything else as you wrote it.
我正在尝试克隆盒装特征的载体。
自然地简单地在实现我的特征的所有结构上推导 Clone
是不够的,因为编译器在编译时不知道所有实现特征的结构都具有 Clone
.
好的,所以我随后尝试使用 Clone
作为超级特征,但这只会导致标题中的错误。我不知所措。
这是最小的工作实现(或者不工作,因为我不能克隆)
#![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
中的 elements
向量变成 Vec<Box<MusicElement + Clone>>
,但那也没用。
我无法在网上找到任何有用的解决方案,所以这是我的问题:如何使代码可克隆?
解决方案在于结合目前评论中的建议 - 'static + MusicElement + Clone
) types. The only subsequent step necessary for your implementation is changing the Note.name
field's type from &'a str
to String
,
#![allow(dead_code, unused_macros)]
use std::fmt::Debug;
trait MusicElement: MusicElementClone + Debug {
fn duration(&self) -> f32;
}
trait MusicElementClone {
fn clone_box(&self) -> Box<MusicElement>;
}
impl<T: 'static + MusicElement + Clone> MusicElementClone for T {
fn clone_box(&self) -> Box<MusicElement> {
Box::new(self.clone())
}
}
impl Clone for Box<MusicElement> {
fn clone(&self) -> Box<MusicElement> {
self.clone_box()
}
}
#[derive(Debug, Clone)]
struct Note {
name: String,
duration: f32,
}
impl MusicElement for Note {
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: String::from("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);
}
编译通过,所以应该足够了!
我的objekt
crate provides a reusable implementation of
之前:
trait MusicElement: Debug + Clone {
fn duration(&self) -> f32;
}
之后:
#[macro_use]
extern crate objekt;
trait MusicElement: Debug + objekt::Clone {
fn duration(&self) -> f32;
}
clone_trait_object!(MusicElement);
// Everything else as you wrote it.