我有一些嵌套的结构,无法创建父结构的后引用。 example:
struct Foo<'a> {
parent: &'a Bar<'a>,
}
impl<'a> Foo<'a> {
fn new(parent: &'a Bar) -> Self {
Foo { parent: parent }
}
fn hello_world(&self) -> String {
self.parent.hello().to_owned() + " world"
}
}
struct Bar<'b> {
child: Option<Foo<'b>>,
data: &'static str,
}
impl<'b> Bar<'b> {
fn new() -> Self {
Bar {
child: None,
data: "hello",
}
}
fn hello(&self) -> &str {
self.data
}
fn get_foo(&self) -> Option<&Foo> {
self.child.as_ref()
}
}
fn main() {
let bar = Bar::new();
assert_eq!("hello", bar.hello());
match bar.get_foo() {
Some(foo) => assert_eq!("hello world", foo.hello_world()),
None => (),
}
}
如何将None
替换为Some<Foo>
并引用Bar
?到目前为止,我不确定这是可能的。
答案 0 :(得分:1)
这不是您的示例的简单解决方案,但我相信您可以使用Arc
和RwLock
创建“循环引用”。 API不完全相同(例如,parent
是一个可选字段),我重命名了一些对象,它肯定更详细,但是你的测试通过了!
use std::sync::{Arc, RwLock};
#[derive(Debug, Clone)]
struct Child {
parent: Option<Arc<RwLock<Parent>>>
}
impl Child {
fn new() -> Self {
Child {
parent: None
}
}
fn hello_world(&self) -> String {
let x = self.parent.as_ref().unwrap().clone();
let y = x.read().unwrap();
y.hello().to_owned() + " world"
}
}
#[derive(Debug, Clone)]
struct Parent {
child: Option<Arc<RwLock<Child>>>,
data: &'static str
}
impl Parent {
fn new() -> Self {
Parent {
child: None,
data: "hello"
}
}
fn hello(&self) -> &str {
self.data
}
fn get_child(&self) -> Option<Arc<RwLock<Child>>> {
self.child.as_ref().map(|x| x.clone() )
}
}
fn main() {
let parent = Arc::new(RwLock::new(Parent::new()));
let child = Arc::new(RwLock::new(Child::new()));
parent.write().unwrap().child = Some(child.clone());
child.write().unwrap().parent = Some(parent.clone());
assert_eq!("hello", parent.read().unwrap().hello());
{
let x = parent.read().unwrap();
match x.get_child() {
Some(child) => { assert_eq!("hello world", child.read().unwrap().hello_world()); }
None => {},
}
}
}
答案 1 :(得分:1)
我有一个类似的问题,对建议的解决方案并不完全满意。
如果您的结构确实是嵌套的(即,您有一个“父母”和“孩子”的概念,每个孩子都有一个唯一的父母),那么父母应该拥有该孩子是很自然的事情。因此,使用Rc
/ Arc
(旨在允许多个所有者使用)看起来不是正确的解决方案-尤其如此,因为@Shepmaster指出,它“鼓励”(或至少允许)创建循环引用。
我的想法是让每个孩子都拥有指向其父母的原始指针:
pub struct Node {
parent: *mut Node,
// ...
}
由于节点是由其父节点拥有的,因此只能在借用其父节点(分别以可变方式借用)时借用(相应地可变借用)。因此,在这种情况下,将self.parent
强制转换为&Node
(如果&mut Node
是可变的,则分别为self
)应该是安全的。
impl Node {
pub fn get_parent(&self) -> Option<&Node> {
unsafe { self.parent.as_ref() }
}
pub fn get_mut_parent(&mut self) -> Option<&mut Node> {
unsafe { self.parent.as_mut() }
}
}
但是,这要求父节点的地址永不更改(即父节点永不移动)。这可以通过仅处理 boxed 节点来实现。
pub struct Node {
parent: *mut Node,
children: Vec<Box<Node>>,
// ..
}
impl Node {
pub fn new(data: &str) -> Box<Node> {
Box::new(Node {
parent: std::ptr::null_mut(),
children: vec![],
// ..
})
}
pub fn append_child(&mut self, mut child: Box<Node>) -> usize {
child.parent = self;
self.children.push(child);
self.children.len() - 1
}
}
我实现了一个完整的示例in the playground。