在Rust中将结构的字段声明为其他字段的函数

bmvo0sr5  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(129)

我在Rust中有一个结构体A,它有3个字段:abc

struct A {
  pub a: typeA,
  pub b: typeB,
  pub c: typeC
};

typeAtypeBtypeC是三种不同类型的结构体。typeBtypeC具有typeA作为依赖项。例如

struct typeB {
    pub bb: typeA,
};

struct typeC {
    pub cc: typeA,
};

并且typeA定义如下:

struct typeA {
    pub aa: String,
};

我可以这样示例化A

let instance_a = A {
    a1 : typeA {aa: "a".to_string()},
    b1 : typeB {bb: typeA {aa: "a".to_string()}},
    c1 : typeC {cc: typeA {aa: "a".to_string()}},
};

正如你在这里看到的b1c1都依赖于a1。我的问题是,有没有一种更干净的方法可以让字段b1在编译时直接依赖于a1,而不必像instance_a中所示的那样在每种情况下分别为b1c1声明它们?
长期目标是在a1被修改时自动更新b1c1。换句话说,如果我想决定将a1的值更新为这个a1: typeA {aa : "b".to_string()},那么b1c1应该自动更新。
我尝试过用下面的方法来解决这个问题。我已经推导出typeAtypeBtypeC是可克隆的。

impl A {
    pub fn create(a: &str) -> Self {
        let old_instance = typeA {aa : a.to_string()};
        A {
            a1: old_instance.clone(),
            b1: typeB {bb: old_instance.clone()},
            c1: typeC {cc: old_instance.clone()},
        }
    }
}

因此,每当我想更新A中发生的任何事情时,我只需调用A::create("hello_world")

8yoxcaq7

8yoxcaq71#

既然你想在a被修改时自动更新B和c,那么你要么想保留对a的引用,要么想和Arc拥有共同的所有权。Arc是只读的,所以如果你想修改东西,你需要用内部可变性来做。有几种方法可以做到这一点。这里有一种(如果你不需要多线程,用Rc替换Arc)

use std::cell::RefCell;
use std::sync::Arc;

#[derive(Debug)]
struct A {
    pub a: Arc<typeA>,
    pub b: typeB,
    pub c: typeC
}

#[derive(Debug)]
struct typeB {
    pub bb: Arc<typeA>
}

#[derive(Debug)]
struct typeC {
    pub cc: Arc<typeA>
}

#[derive(Debug)]
struct typeA {
    pub aa: RefCell<String>
}

fn main() {
    let mut aa = Arc::new(typeA { aa: RefCell::new(String::from("test1")) });
    let instance_a = A {
        a : aa.clone(),
        b : typeB {bb: aa.clone()},
        c : typeC {cc: aa.clone()},
    };
    println!("{:?}", instance_a);
    // modify aa
    *aa.aa.borrow_mut() = String::from("test2");
    println!("{:?}", instance_a);
}

输出量:

A { a: typeA { aa: RefCell { value: "test1" } }, b: typeB { bb: typeA { aa: RefCell { value: "test1" } } }, c: typeC { cc: typeA { aa: RefCell { value: "test1" } } } }
A { a: typeA { aa: RefCell { value: "test2" } }, b: typeB { bb: typeA { aa: RefCell { value: "test2" } } }, c: typeC { cc: typeA { aa: RefCell { value: "test2" } } } }

相关问题