I’m a bit confused about how to handle the different reference and smart pointer types in this example:
use std::rc::Rc;
use std::sync::Arc;
struct Data{}
trait ApiClient {
fn load_data() -> Vec<Data>;
}
struct HttpApiClient {}
impl ApiClient for HttpApiClient {
fn load_data() -> Vec<Data>{
todo!()
}
}
struct PageA<'a, A: ApiClient>{
dep: &'a A
}
struct PageB<A: ApiClient> {
dep: Rc<A>
}
struct PageC<A: ApiClient> {
dep: Arc<A>
}
enum Pages<'a, A: ApiClient> {
A(PageA<'a, A>),
B(PageB<A>),
C(PageC<A>)
}
struct Application<'a, A: ApiClient> {
current_page: Option<Pages<'a, A>>,
dependency: Arc<A>
}
impl <'a, A: ApiClient> Application<'a, A> {
fn new(dependency: Arc<A>) -> Self {
Application {
current_page: None,
dependency
}
}
fn page_a(&mut self) {
// I cannot construct PageA here because it requires a reference to the ApiClient.
// When using .as_ref the reference is not valid long enough
todo!()
}
fn page_b(&mut self) {
// I cannot construct PageB here because it requires a Rc<ApiClient> but I have an Arc<ApiClient>.
todo!()
}
fn page_c(&mut self) {
self.current_page = Some(Pages::C(PageC { dep:self.dependency.clone() }));
}
}
fn main() {
todo!()
}
This simplified example illustrates my issue. I have an Application
struct that can display one of three different pages. Each page has a dependency on an instance of the ApiClient
trait, and here’s where the problem arises:
PageA
requires a regular reference (&ApiClient
).PageB
requires anRc<ApiClient>
.PageC
requires anArc<ApiClient>
.
The Application
struct initializes these pages on demand, but since it holds the dependency as an Arc
, I can only construct PageC
without issues.
What I’ve considered
- I could modify all three page structs to use
Arc<ApiClient>
, but I don’t want the need of one struct to influence the design of the other ones. - I could implement the
ApiClient
trait for&HttpApiClient
,Rc<HttpApiClient>
, andArc<HttpApiClient>
. This seems feasible, but I’m unsure if it’s considered best practice or introduces unnecessary complexity. - I know that
HttpApiClient
can be cheaply cloned in this example, but in my actual application, the dependency is more expensive to clone and must be shared between pages.
1