我希望有一个CatMaker
结构可以创建Cat
,但在内部存储对它的引用,以便以后可以调用Cat
(也许有CatMaker.get_child_color(&self)
功能)。我相信这意味着CatMaker
不能比Cat
更长(否则它会尝试顺从而Cat
不会存在)并且编译器似乎同意。
以下是我想要做的代码示例:
pub enum CoatColor {
Black,
Tabby,
}
pub struct Cat {
color: CoatColor,
}
pub struct CatMaker<'a> {
child: Option<&'a Cat>,
}
impl<'a> CatMaker<'a> {
pub fn new() -> CatMaker<'a> {
CatMaker{ child: None }
}
pub fn make_cat(&mut self, color: CoatColor) -> Cat {
let new_cat = Cat{ color: color };
self.child = Some(&new_cat); // commenting out this line will allow it to compile
new_cat
}
}
fn main() {
let mut my_cat_maker = CatMaker::new();
let mut my_cat = my_cat_maker.make_cat(CoatColor::Black);
my_cat.color = CoatColor::Tabby;
}
我无法确定如何在self.child
中指定CatMaker.make_cat
的生命周期。
答案 0 :(得分:2)
您可以CatMaker
拥有Cat
,make_cat
会返回对Cat
的引用,而不是返回Cat
本身。
pub enum CoatColor {
Black,
Tabby,
}
pub struct Cat {
color: CoatColor,
}
pub struct CatMaker {
child: Option<Cat>,
}
impl CatMaker {
pub fn new() -> CatMaker {
CatMaker { child: None }
}
pub fn make_cat(&mut self, color: CoatColor) -> &mut Cat {
let new_cat = Cat { color: color };
self.child = Some(new_cat);
self.child.as_mut().unwrap()
}
}
fn main() {
let mut my_cat_maker = CatMaker::new();
let mut my_cat = my_cat_maker.make_cat(CoatColor::Black);
my_cat.color = CoatColor::Tabby;
}
但是,这有一个很大的限制:只要保持my_cat_maker
的结果,就不能使用make_cat
- 这里,它存储在my_cat
中,所以在my_cat_maker
超出范围之前,您无法使用my_cat
。那是因为my_cat
在my_cat_maker
上保留了一个可变的借位,并且Rust不允许两个可变借位同时在同一个对象上使用。
如果您不接受此限制,则需要使用其他工具来管理Cat
的生命周期。这样的工具是Rc
,它是对象的引用计数引用。如果您还需要能够改变Cat
,则需要将Rc
与RefCell
结合,这样可以在Rc
中改变对象。
use std::cell::RefCell;
use std::rc::Rc;
pub enum CoatColor {
Black,
Tabby,
}
pub struct Cat {
color: CoatColor,
}
pub struct CatMaker {
child: Option<Rc<RefCell<Cat>>>,
}
impl CatMaker {
pub fn new() -> CatMaker {
CatMaker { child: None }
}
pub fn make_cat(&mut self, color: CoatColor) -> Rc<RefCell<Cat>> {
let new_cat = Rc::new(RefCell::new(Cat { color: color }));
self.child = Some(new_cat.clone());
new_cat
}
}
fn main() {
let mut my_cat_maker = CatMaker::new();
let my_cat = my_cat_maker.make_cat(CoatColor::Black);
my_cat.borrow_mut().color = CoatColor::Tabby;
}
在make_cat
中,.clone()
调用克隆Rc
对象,该对象对同一对象进行新引用,增加引用计数。删除所有相关的Rc
对象后,将删除引用计数对象。
在main
中,我们需要致电borrow_mut()
才能访问Cat
。 borrow_mut()
返回一个RefMut
对象,可以保护Cat
不被借用,直到RefMut
被删除。如果您在可变借入激活时尝试再次借用Cat
,您的程序将会出现恐慌。