gpt4 book ai didi

rust - 具有共同值(value)的分层 API

转载 作者:行者123 更新时间:2023-11-29 07:58:48 24 4
gpt4 key购买 nike

我有一个 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.

parent 拥有一个家庭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

我已经尝试了几种方法来实现这一点,包括将 secret 传递给家谱。

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 实现为 Parenttrait,并保持单独的客户端 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();

有什么好的方法可以将这个 secret 传给家谱吗?只有一个 parent ,所以它归 parent 所有是有道理的。如何在后代借用?

最佳答案

您可以将 Secret 的所有权移到 Parent 之外,只共享对 Secret 的引用:

#[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();
}

playground


另一种解决方案是使用 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();
}

playground

关于rust - 具有共同值(value)的分层 API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41888242/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com