我有一个Parent
结构,一个Child
结构和一个GrandChild
结构:
pub struct Parent {
pub child_a: ChildA,
pub child_b: ChildB,
family_secret: Secret,
}
pub struct ChildA {
pub grand_child_x: GrandChildX,
pub grand_child_y: GrandChildY,
}
pub struct GrandChildX {}
// etc.
父母拥有一个家庭Secret
,我希望孙子女可以在他们的impl
中访问。
impl GrandChildX {
pub fn method(&self) {
// Here I need to use the family secret.
}
}
我正在尝试公开分层API。
let parent = Parent::new("our secret");
parent.child_a.grand_child_x.method();
parent.child_b.grand_child_y.method(); // slightly different
我尝试了几种方法来实现这一目标,包括将秘密传递到家谱中。
pub struct ChildA {
family_secret: Secret,
// ...
}
pub struct ChildB {
family_secret: Secret,
// ...
}
这在儿童之间移动值时遇到了问题(已移至ChildA::new(family_secret: secret)
)。
impl Parent {
pub fn new(secret) -> Parent {
let secret = Secret::new(secret);
Parent {
family_secret: secret,
child_a: ChildA { family_secret: &secret },
// error move after use ---------^
}
}
我尝试将其作为参考传递下去,但之后该值的存活时间不够长:
impl Parent {
pub fn new(secret) -> Parent {
let secret = Secret::new(secret);
Parent {
child_a: ChildA { family_secret: &secret },
// ^-----<
// error does not live long enough ----^
}
}
我唯一的成功就是将method
作为trait
Parent
实施,并保留单独的客户struct
。
pub struct ChildAClient<'a> {
family_secret: &'a Secret,
}
pub trait ChildA {
fn child_a(&self) -> ChildAClient,
}
impl ChildA for Parent {
fn child_a(&self) -> ChildAClient {
ChildAClient {
family_secret: &self.family_secret,
}
}
}
// Same for ChildB, etc.
pub struct GrandChildXClient<'a> {
family_secret: &'a Secret,
}
pub trait GrandChildX {
fn grand_child_x(&self) -> GrandChildXClient,
}
impl<'a> GrandChildX for ChildAClient<'a> {
fn grand_child_x(&self) -> GrandChildXClient {
GrandChildXClient {
family_secret: self.family_secret,
}
}
}
这不仅让作者感到笨拙,而且它提供了一个笨重的API,因为我必须导入所有这些特征,并调用特征方法来遍历家谱:
use my_api::child_a::ChildA;
use my_api::child_a::grand_child_x::GrandChildX;
use my_api::child_b::ChildB;
use my_api::child_b::grand_child_Y::GrandChildY;
let parent = my_api::Parent::new("my secret");
parent.child_a().grand_child_x().method();
parent.child_b().grand_child_y().method();
有没有一种方法可以将这个秘密传递到家谱中?只有一个父母,所以它由父母拥有是有道理的。我怎样才能在后代借用它?
答案 0 :(得分:4)
您可以将“秘密”的所有权移到“父级”之外,只是共享对该秘密的引用:
#[derive(Clone)]
pub struct Parent<'a> {
pub child_a: ChildA<'a>,
family_secret: &'a str,
}
#[derive(Clone)]
pub struct ChildA<'a> {
pub grand_child_x: GrandChildX<'a>,
family_secret: &'a str,
}
#[derive(Clone)]
pub struct GrandChildX<'a> {
family_secret: &'a str,
}
impl<'a> Parent<'a> {
pub fn new(secret: &'a str) -> Parent<'a> {
Parent {
family_secret: secret,
child_a: ChildA::new(secret),
}
}
}
impl<'a> ChildA<'a> {
pub fn new(secret: &'a str) -> ChildA<'a> {
ChildA {
family_secret: secret,
grand_child_x: GrandChildX::new(secret),
}
}
}
impl<'a> GrandChildX<'a> {
pub fn new(secret: &'a str) -> GrandChildX<'a> {
GrandChildX{family_secret: secret}
}
pub fn method(&self) {
println!("Secret: {} from grand child", self.family_secret);
}
}
fn main() {
let secret = "my secret".to_string();
let parent = Parent::new(&secret);
parent.child_a.grand_child_x.method();
}
另一种解决方案是使用reference counting pointer Rc<T>
:
use std::rc::Rc;
#[derive(Clone)]
pub struct Parent {
pub child_a: ChildA,
family_secret: Rc<String>,
}
#[derive(Clone)]
pub struct ChildA {
pub grand_child_x: GrandChildX,
family_secret: Rc<String>,
}
#[derive(Clone)]
pub struct GrandChildX {
family_secret: Rc<String>,
}
impl Parent {
pub fn new(secret: String) -> Parent {
let secret = Rc::new(secret);
Parent {
family_secret: secret.clone(),
child_a: ChildA::new(secret),
}
}
}
impl ChildA {
pub fn new(secret: Rc<String>) -> ChildA {
ChildA {
family_secret: secret.clone(),
grand_child_x: GrandChildX::new(secret),
}
}
}
impl GrandChildX {
pub fn new(secret: Rc<String>) -> GrandChildX {
GrandChildX{family_secret: secret}
}
pub fn method(&self) {
println!("Secret: {} from grand child", self.family_secret);
}
}
fn main() {
let secret = "my secret".to_string();
let parent = Parent::new(secret);
parent.child_a.grand_child_x.method();
}