You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I found that `Rc<RefCell<..>>` may actually be useful in some cases.
I decided to move this case into the repo for a quick reference.
* Use Rust 1.53 for GitHub Workflows
* Fix clippy errors
* Update behavioral/mediator/README.md
A common implementation in object-oriented languages looks like the following
45
+
pseudo-code:
46
+
47
+
```java
48
+
Controller controller =newController();
49
+
50
+
// Every component has a link to a mediator (controller).
51
+
component1.setController(controller);
52
+
component2.setController(controller);
53
+
component3.setController(controller);
54
+
55
+
// A mediator has a link to every object.
56
+
controller.add(component1);
57
+
controller.add(component2);
58
+
controller.add(component2);
59
+
```
60
+
61
+
Now, let's read this in **Rust** terms: _"**mutable** structures have
62
+
**mutable** references to a **shared mutable** object (mediator) which in turn
63
+
has mutable references back to those mutable structures"_.
64
+
65
+
Basically, you can start to imagine the unfair battle against the Rust compiler
66
+
and its borrow checker. It seems like a solution introduces more problems:
67
+
68
+

69
+
70
+
1. Imagine that the control flow starts at point 1 (Checkbox) where the 1st
71
+
**mutable** borrow happens.
72
+
2. The mediator (Dialog) interacts with another object at point 2 (TextField).
73
+
3. The TextField notifies the Dialog back about finishing a job and that leads
74
+
to a **mutable** action at point 3... Bang!
75
+
76
+
The second mutable borrow breaks the compilation with an error
77
+
(the first borrow was on the point 1).
78
+
79
+
## Cross-Referencing with `Rc<RefCell<..>>`
80
+
81
+
```bash
82
+
cargo run --bin mediator-rc-refcell
83
+
```
84
+
85
+
`Rc<RefCell<..>>` hides objects from compiler eyes inside of an opaque smart pointer.
86
+
In this case, borrow checks move into the runtime that means panicking in case of
87
+
borrow rules violation.
88
+
89
+
There is an example of a [Station Manager example in Go][4]. Trying to make it
90
+
with Rust leads to mimicking a typical OOP through reference counting and
91
+
borrow checking with mutability in runtime (which has quite unpredictable
92
+
behavior in runtime with panics here and there).
93
+
94
+
Key points:
95
+
96
+
1. All trait methods are **read-only**: immutable `self` and immutable parameters.
97
+
2.`Rc`, `RefCell` are extensively used under the hood to take responsibility
98
+
for the mutable borrowing from compiler to runtime. Invalid implementation
99
+
will lead to panic in runtime.
100
+
27
101
## Top-Down Ownership
28
102
29
-
The key point is thinking in terms of OWNERSHIP.
103
+
```bash
104
+
cargo run --bin mediator-top-down
105
+
```
106
+
107
+
☝ The key point is thinking in terms of OWNERSHIP.
108
+
109
+

30
110
31
111
1. A mediator takes ownership of all components.
32
-
2. A component doesn't preserve a reference to a mediator. Instead, it gets the reference via a method call.
112
+
2. A component doesn't preserve a reference to a mediator. Instead, it gets the
113
+
reference via a method call.
33
114
34
115
```rust
35
116
// A train gets a mediator object by reference.
@@ -46,8 +127,12 @@ The key point is thinking in terms of OWNERSHIP.
46
127
}
47
128
```
48
129
49
-
3. Control flow starts from `fn main()` where the mediator receives external events/commands.
50
-
4.`Mediator` trait for the interaction between components (`notify_about_arrival`, `notify_about_departure`) is not the same as its external API for receiving external events (`accept`, `depart` commands from the main loop).
130
+
3. Control flow starts from `fn main()` where the mediator receives external
131
+
events/commands.
132
+
4.`Mediator` trait for the interaction between components
133
+
(`notify_about_arrival`, `notify_about_departure`) is not the same as its
134
+
external API for receiving external events (`accept`, `depart` commands from
135
+
the main loop).
51
136
52
137
```rust
53
138
lettrain1=PassengerTrain::new("Train 1");
@@ -68,9 +153,13 @@ The key point is thinking in terms of OWNERSHIP.
`Rc<RefCell<..>>` hides objects from compiler eyes inside of an opaque smart pointer.
12
+
In this case, borrow checks move into the runtime that means panicking in case of
13
+
borrow rules violation.
14
+
15
+
There is an example of a [Station Manager example in Go][4]. Trying to make it
16
+
with Rust leads to mimicking a typical OOP through reference counting and
17
+
borrow checking with mutability in runtime (which has quite unpredictable
18
+
behavior in runtime with panics here and there).
19
+
20
+
Key points:
21
+
22
+
1. All methods are read-only: immutable `self` and parameters.
23
+
2.`Rc`, `RefCell` are extensively used under the hood to take responsibility for the mutable borrowing from compilation time to runtime. Invalid implementation will lead to panic in runtime.
0 commit comments