Den*_*hin 20 struct clone traits cloneable rust
我编写了一个程序,它具有特征Animal和Dog实现特征的结构.它还有一个AnimalHouse存储动物作为特征对象的结构Box<Animal>.
trait Animal {
fn speak(&self);
}
struct Dog {
name: String,
}
impl Dog {
fn new(name: &str) -> Dog {
return Dog {
name: name.to_string(),
};
}
}
impl Animal for Dog {
fn speak(&self) {
println!{"{}: ruff, ruff!", self.name};
}
}
struct AnimalHouse {
animal: Box<Animal>,
}
fn main() {
let house = AnimalHouse {
animal: Box::new(Dog::new("Bobby")),
};
house.animal.speak();
}
Run Code Online (Sandbox Code Playgroud)
它返回"Bobby:ruff,ruff!" 正如所料,但如果我尝试克隆house编译器返回错误:
fn main() {
let house = AnimalHouse {
animal: Box::new(Dog::new("Bobby")),
};
let house2 = house.clone();
house2.animal.speak();
}
Run Code Online (Sandbox Code Playgroud)
error[E0599]: no method named `clone` found for type `AnimalHouse` in the current scope
--> src/main.rs:31:24
|
23 | struct AnimalHouse {
| ------------------ method `clone` not found for this
...
31 | let house2 = house.clone();
| ^^^^^
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `clone`, perhaps you need to implement it:
candidate #1: `std::clone::Clone`
Run Code Online (Sandbox Code Playgroud)
我#[derive(Clone)]之前试图添加struct AnimalHouse并得到另一个错误:
error[E0277]: the trait bound `Animal: std::clone::Clone` is not satisfied
--> src/main.rs:25:5
|
25 | animal: Box<Animal>,
| ^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `Animal`
|
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::boxed::Box<Animal>`
= note: required by `std::clone::Clone::clone`
Run Code Online (Sandbox Code Playgroud)
如何使结构可AnimalHouse克隆?一般来说,积极使用特质对象是惯用的吗?
DK.*_*DK. 23
有一些问题.首先,没有什么要求Animal也可以实现Clone.您可以通过更改特征定义来解决此问题:
trait Animal: Clone {
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
这将导致Animal不再是对象安全,这意味着Box<Animal>它将变得无效,因此不是很好.
您可以做的是插入一个额外的步骤.要惠特(加上@ChrisMorgan的评论).
trait Animal: AnimalClone {
fn speak(&self);
}
// Splitting AnimalClone into its own trait allows us to provide a blanket
// implementation for all compatible types, without having to implement the
// rest of Animal. In this case, we implement it for all types that have
// 'static lifetime (*i.e.* they don't contain non-'static pointers), and
// implement both Animal and Clone. Don't ask me how the compiler resolves
// implementing AnimalClone for Animal when Animal requires AnimalClone; I
// have *no* idea why this works.
trait AnimalClone {
fn clone_box(&self) -> Box<Animal>;
}
impl<T> AnimalClone for T
where
T: 'static + Animal + Clone,
{
fn clone_box(&self) -> Box<Animal> {
Box::new(self.clone())
}
}
// We can now implement Clone manually by forwarding to clone_box.
impl Clone for Box<Animal> {
fn clone(&self) -> Box<Animal> {
self.clone_box()
}
}
#[derive(Clone)]
struct Dog {
name: String,
}
impl Dog {
fn new(name: &str) -> Dog {
Dog {
name: name.to_string(),
}
}
}
impl Animal for Dog {
fn speak(&self) {
println!("{}: ruff, ruff!", self.name);
}
}
#[derive(Clone)]
struct AnimalHouse {
animal: Box<Animal>,
}
fn main() {
let house = AnimalHouse {
animal: Box::new(Dog::new("Bobby")),
};
let house2 = house.clone();
house2.animal.speak();
}
Run Code Online (Sandbox Code Playgroud)
通过介绍clone_box,我们可以解决尝试克隆特征对象的问题.
我的objekt箱子实现的可重复使用的版本DK。的回答。有了它,您只需很少的更改就可以使原始代码正常工作。
objekt::Clone作为的特征Animal,要求每个动物实现都是可克隆的。Clone实现Box<Animal>。#[macro_use] extern crate objekt;
trait Animal: objekt::Clone {
fn speak(&self);
}
clone_trait_object!(Animal);
#[derive(Clone)]
struct Dog {
name: String,
}
impl Dog {
fn new(name: &str) -> Dog {
Dog { name: name.to_owned() }
}
}
impl Animal for Dog {
fn speak(&self) {
println!{"{}: ruff, ruff!", self.name};
}
}
#[derive(Clone)]
struct AnimalHouse {
animal: Box<Animal>,
}
fn main() {
let house = AnimalHouse {
animal: Box::new(Dog::new("Bobby")),
};
let house2 = house.clone();
house2.animal.speak();
}
Run Code Online (Sandbox Code Playgroud)
在以前的答案正确地回答了关于存储盒装特质对象的问题。
关于标题,而不是使用特质对象的惯用方式,可以采用另一种解决方案,即使用Rc智能指针代替a Box:这避免了解决对象安全性的变通方法:
#[derive(Clone)]
struct AnimalHouse {
animal: Rc<Animal>,
}
fn main() {
let house = AnimalHouse { animal: Rc::new(Dog::new("Bobby")) };
let house2 = house.clone();
house2.animal.speak();
}
Run Code Online (Sandbox Code Playgroud)
注意:Rc<T>仅用于单线程方案;还有Arc<T>。
| 归档时间: |
|
| 查看次数: |
3891 次 |
| 最近记录: |