pub struct ObservableProperty<T> { /* private fields */ }Expand description
A thread-safe observable property that notifies observers when its value changes
This type wraps a value of type T and allows multiple observers to be notified
whenever the value is modified. All operations are thread-safe and can be called
from multiple threads concurrently.
§Type Requirements
The generic type T must implement:
Clone: Required for returning values and passing them to observersSend: Required for transferring between threadsSync: Required for concurrent access from multiple threads'static: Required for observer callbacks that may outlive the original scope
§Examples
use observable_property::ObservableProperty;
use std::sync::Arc;
let property = ObservableProperty::new("initial".to_string());
let observer_id = property.subscribe(Arc::new(|old, new| {
println!("Changed from '{}' to '{}'", old, new);
})).map_err(|e| {
eprintln!("Failed to subscribe: {}", e);
e
})?;
property.set("updated".to_string()).map_err(|e| {
eprintln!("Failed to set value: {}", e);
e
})?; // Prints: Changed from 'initial' to 'updated'
property.unsubscribe(observer_id).map_err(|e| {
eprintln!("Failed to unsubscribe: {}", e);
e
})?;Implementations§
Source§impl<T: Clone + Send + Sync + 'static> ObservableProperty<T>
impl<T: Clone + Send + Sync + 'static> ObservableProperty<T>
Sourcepub fn new(initial_value: T) -> Self
pub fn new(initial_value: T) -> Self
Creates a new observable property with the given initial value
§Arguments
initial_value- The starting value for this property
§Examples
use observable_property::ObservableProperty;
let property = ObservableProperty::new(42);
match property.get() {
Ok(value) => assert_eq!(value, 42),
Err(e) => eprintln!("Failed to get property value: {}", e),
}Examples found in repository?
16 fn new(name: String, age: i32) -> Self {
17 Self {
18 name: ObservableProperty::new(name),
19 age: ObservableProperty::new(age),
20 }
21 }
22
23 fn get_name(&self) -> Result<String, observable_property::PropertyError> {
24 self.name.get()
25 }
26
27 fn set_name(&self, new_name: String) -> Result<(), observable_property::PropertyError> {
28 self.name.set(new_name)
29 }
30
31 fn get_age(&self) -> Result<i32, observable_property::PropertyError> {
32 self.age.get()
33 }
34
35 fn set_age(&self, new_age: i32) -> Result<(), observable_property::PropertyError> {
36 self.age.set(new_age)
37 }
38
39 fn celebrate_birthday(&self) -> Result<(), observable_property::PropertyError> {
40 let current_age = self.age.get()?;
41 self.age.set(current_age + 1)
42 }
43}
44
45fn main() -> Result<(), Box<dyn std::error::Error>> {
46 println!("=== Observable Property Basic Example ===\n");
47
48 // Create a person
49 let person = Person::new("Alice".to_string(), 25);
50
51 // Subscribe to name changes
52 let name_observer_id = person.name.subscribe(Arc::new(|old_name, new_name| {
53 println!("📝 Name changed: '{}' → '{}'", old_name, new_name);
54 }))?;
55
56 // Subscribe to age changes
57 let age_observer_id = person.age.subscribe(Arc::new(|old_age, new_age| {
58 println!("🎂 Age changed: {} → {}", old_age, new_age);
59 }))?;
60
61 // Subscribe to only significant age changes (milestones)
62 let milestone_observer_id = person.age.subscribe_filtered(
63 Arc::new(|_old_age, new_age| {
64 println!("🎉 Milestone reached! {} is now a special age: {}",
65 if *new_age >= 18 { "Adult" } else { "Child" }, new_age);
66 }),
67 |old_age, new_age| {
68 // Notify on milestone ages
69 let milestones = [18, 21, 30, 40, 50, 65];
70 milestones.contains(new_age) ||
71 (milestones.contains(old_age) && !milestones.contains(new_age))
72 }
73 )?;
74
75 println!("Initial state:");
76 println!(" Name: {}", person.get_name()?);
77 println!(" Age: {}\n", person.get_age()?);
78
79 // Demonstrate property changes
80 println!("Making changes...\n");
81
82 // Change name
83 person.set_name("Alice Johnson".to_string())?;
84
85 // Age up a few times
86 person.celebrate_birthday()?;
87 person.celebrate_birthday()?;
88 person.celebrate_birthday()?;
89
90 // Change to milestone age
91 person.set_age(21)?;
92
93 // Direct property access
94 println!("\nDirect property access:");
95 let simple_property = ObservableProperty::new(100);
96
97 simple_property.subscribe(Arc::new(|old, new| {
98 println!("💰 Value changed: {} → {}", old, new);
99 }))?;
100
101 simple_property.set(200)?;
102 simple_property.set(150)?;
103
104 // Cleanup observers
105 person.name.unsubscribe(name_observer_id)?;
106 person.age.unsubscribe(age_observer_id)?;
107 person.age.unsubscribe(milestone_observer_id)?;
108
109 println!("\n✅ Example completed successfully!");
110 Ok(())
111}More examples
Sourcepub fn get(&self) -> Result<T, PropertyError>
pub fn get(&self) -> Result<T, PropertyError>
Gets the current value of the property
This method acquires a read lock, which allows multiple concurrent readers but will block if a writer currently holds the lock.
§Returns
Ok(T) containing a clone of the current value, or Err(PropertyError)
if the lock is poisoned.
§Examples
use observable_property::ObservableProperty;
let property = ObservableProperty::new("hello".to_string());
match property.get() {
Ok(value) => assert_eq!(value, "hello"),
Err(e) => eprintln!("Failed to get property value: {}", e),
}Examples found in repository?
23 fn get_name(&self) -> Result<String, observable_property::PropertyError> {
24 self.name.get()
25 }
26
27 fn set_name(&self, new_name: String) -> Result<(), observable_property::PropertyError> {
28 self.name.set(new_name)
29 }
30
31 fn get_age(&self) -> Result<i32, observable_property::PropertyError> {
32 self.age.get()
33 }
34
35 fn set_age(&self, new_age: i32) -> Result<(), observable_property::PropertyError> {
36 self.age.set(new_age)
37 }
38
39 fn celebrate_birthday(&self) -> Result<(), observable_property::PropertyError> {
40 let current_age = self.age.get()?;
41 self.age.set(current_age + 1)
42 }More examples
21 fn get_name(&self) -> Result<String, observable_property::PropertyError> {
22 self.name.get()
23 }
24
25 fn set_name(&self, new_name: String) -> Result<(), observable_property::PropertyError> {
26 self.name.set(new_name)
27 }
28
29 fn get_age(&self) -> Result<i32, observable_property::PropertyError> {
30 self.age.get()
31 }
32
33 fn set_age(&self, new_age: i32) -> Result<(), observable_property::PropertyError> {
34 self.age.set(new_age)
35 }
36
37 fn celebrate_birthday(&self) -> Result<(), observable_property::PropertyError> {
38 let current_age = self.age.get()?;
39 self.age.set(current_age + 1)
40 }Sourcepub fn set(&self, new_value: T) -> Result<(), PropertyError>
pub fn set(&self, new_value: T) -> Result<(), PropertyError>
Sets the property to a new value and notifies all observers
This method will:
- Acquire a write lock (blocking other readers/writers)
- Update the value and capture a snapshot of observers
- Release the lock
- Notify all observers sequentially with the old and new values
Observer notifications are wrapped in panic recovery to prevent one misbehaving observer from affecting others.
§Arguments
new_value- The new value to set
§Returns
Ok(()) if successful, or Err(PropertyError) if the lock is poisoned.
§Examples
use observable_property::ObservableProperty;
use std::sync::Arc;
let property = ObservableProperty::new(10);
property.subscribe(Arc::new(|old, new| {
println!("Value changed from {} to {}", old, new);
})).map_err(|e| {
eprintln!("Failed to subscribe: {}", e);
e
})?;
property.set(20).map_err(|e| {
eprintln!("Failed to set property value: {}", e);
e
})?; // Triggers observer notificationExamples found in repository?
27 fn set_name(&self, new_name: String) -> Result<(), observable_property::PropertyError> {
28 self.name.set(new_name)
29 }
30
31 fn get_age(&self) -> Result<i32, observable_property::PropertyError> {
32 self.age.get()
33 }
34
35 fn set_age(&self, new_age: i32) -> Result<(), observable_property::PropertyError> {
36 self.age.set(new_age)
37 }
38
39 fn celebrate_birthday(&self) -> Result<(), observable_property::PropertyError> {
40 let current_age = self.age.get()?;
41 self.age.set(current_age + 1)
42 }
43}
44
45fn main() -> Result<(), Box<dyn std::error::Error>> {
46 println!("=== Observable Property Basic Example ===\n");
47
48 // Create a person
49 let person = Person::new("Alice".to_string(), 25);
50
51 // Subscribe to name changes
52 let name_observer_id = person.name.subscribe(Arc::new(|old_name, new_name| {
53 println!("📝 Name changed: '{}' → '{}'", old_name, new_name);
54 }))?;
55
56 // Subscribe to age changes
57 let age_observer_id = person.age.subscribe(Arc::new(|old_age, new_age| {
58 println!("🎂 Age changed: {} → {}", old_age, new_age);
59 }))?;
60
61 // Subscribe to only significant age changes (milestones)
62 let milestone_observer_id = person.age.subscribe_filtered(
63 Arc::new(|_old_age, new_age| {
64 println!("🎉 Milestone reached! {} is now a special age: {}",
65 if *new_age >= 18 { "Adult" } else { "Child" }, new_age);
66 }),
67 |old_age, new_age| {
68 // Notify on milestone ages
69 let milestones = [18, 21, 30, 40, 50, 65];
70 milestones.contains(new_age) ||
71 (milestones.contains(old_age) && !milestones.contains(new_age))
72 }
73 )?;
74
75 println!("Initial state:");
76 println!(" Name: {}", person.get_name()?);
77 println!(" Age: {}\n", person.get_age()?);
78
79 // Demonstrate property changes
80 println!("Making changes...\n");
81
82 // Change name
83 person.set_name("Alice Johnson".to_string())?;
84
85 // Age up a few times
86 person.celebrate_birthday()?;
87 person.celebrate_birthday()?;
88 person.celebrate_birthday()?;
89
90 // Change to milestone age
91 person.set_age(21)?;
92
93 // Direct property access
94 println!("\nDirect property access:");
95 let simple_property = ObservableProperty::new(100);
96
97 simple_property.subscribe(Arc::new(|old, new| {
98 println!("💰 Value changed: {} → {}", old, new);
99 }))?;
100
101 simple_property.set(200)?;
102 simple_property.set(150)?;
103
104 // Cleanup observers
105 person.name.unsubscribe(name_observer_id)?;
106 person.age.unsubscribe(age_observer_id)?;
107 person.age.unsubscribe(milestone_observer_id)?;
108
109 println!("\n✅ Example completed successfully!");
110 Ok(())
111}More examples
25 fn set_name(&self, new_name: String) -> Result<(), observable_property::PropertyError> {
26 self.name.set(new_name)
27 }
28
29 fn get_age(&self) -> Result<i32, observable_property::PropertyError> {
30 self.age.get()
31 }
32
33 fn set_age(&self, new_age: i32) -> Result<(), observable_property::PropertyError> {
34 self.age.set(new_age)
35 }
36
37 fn celebrate_birthday(&self) -> Result<(), observable_property::PropertyError> {
38 let current_age = self.age.get()?;
39 self.age.set(current_age + 1)
40 }Sourcepub fn set_async(&self, new_value: T) -> Result<(), PropertyError>
pub fn set_async(&self, new_value: T) -> Result<(), PropertyError>
Sets the property to a new value and notifies observers asynchronously
This method is similar to set() but spawns observers in background threads
for non-blocking operation. This is useful when observers might perform
time-consuming operations.
Observers are batched into groups and each batch runs in its own thread to limit resource usage while still providing parallelism.
§Arguments
new_value- The new value to set
§Returns
Ok(()) if successful, or Err(PropertyError) if the lock is poisoned.
Note that this only indicates the property was updated successfully;
observer execution happens asynchronously.
§Examples
use observable_property::ObservableProperty;
use std::sync::Arc;
use std::time::Duration;
let property = ObservableProperty::new(0);
property.subscribe(Arc::new(|old, new| {
// This observer does slow work but won't block the caller
std::thread::sleep(Duration::from_millis(100));
println!("Slow observer: {} -> {}", old, new);
})).map_err(|e| {
eprintln!("Failed to subscribe: {}", e);
e
})?;
// This returns immediately even though observer is slow
property.set_async(42).map_err(|e| {
eprintln!("Failed to set value asynchronously: {}", e);
e
})?;Sourcepub fn subscribe(
&self,
observer: Observer<T>,
) -> Result<ObserverId, PropertyError>
pub fn subscribe( &self, observer: Observer<T>, ) -> Result<ObserverId, PropertyError>
Subscribes an observer function to be called when the property changes
The observer function will be called with the old and new values whenever
the property is modified via set() or set_async().
§Arguments
observer- A function wrapped inArcthat takes(&T, &T)parameters
§Returns
Ok(ObserverId) containing a unique identifier for this observer,
or Err(PropertyError) if the lock is poisoned.
§Examples
use observable_property::ObservableProperty;
use std::sync::Arc;
let property = ObservableProperty::new(0);
let observer_id = property.subscribe(Arc::new(|old_value, new_value| {
println!("Property changed from {} to {}", old_value, new_value);
})).map_err(|e| {
eprintln!("Failed to subscribe observer: {}", e);
e
})?;
// Later, unsubscribe using the returned ID
property.unsubscribe(observer_id).map_err(|e| {
eprintln!("Failed to unsubscribe observer: {}", e);
e
})?;Examples found in repository?
44fn main() -> Result<(), Box<dyn std::error::Error>> {
45 println!("=== Observable Property Multithreaded Person Example ===\n");
46
47 let person = Arc::new(Person::new("Bob".to_string(), 30));
48
49 // Subscribe to name changes
50 let name_observer_id = person.name.subscribe(Arc::new(|old_name, new_name| {
51 println!("📝 Name changed: '{}' → '{}'", old_name, new_name);
52 }))?;
53
54 // Subscribe to age changes
55 let age_observer_id = person.age.subscribe(Arc::new(|old_age, new_age| {
56 println!("🎂 Age changed: {} → {}", old_age, new_age);
57 }))?;
58
59 // Spawn threads to update name and age concurrently
60 let person_clone1 = person.clone();
61 let handle1 = thread::spawn(move || {
62 for i in 0..3 {
63 let new_name = format!("Bob #{}", i + 1);
64 person_clone1.set_name(new_name).unwrap();
65 thread::sleep(Duration::from_millis(50));
66 }
67 });
68
69 let person_clone2 = person.clone();
70 let handle2 = thread::spawn(move || {
71 for _ in 0..3 {
72 person_clone2.celebrate_birthday().unwrap();
73 thread::sleep(Duration::from_millis(30));
74 }
75 });
76
77 handle1.join().unwrap();
78 handle2.join().unwrap();
79
80 println!("\nFinal state:");
81 println!(" Name: {}", person.get_name()?);
82 println!(" Age: {}", person.get_age()?);
83
84 // Cleanup observers
85 person.name.unsubscribe(name_observer_id)?;
86 person.age.unsubscribe(age_observer_id)?;
87
88 println!("\n✅ Multithreaded Person example completed successfully!");
89 Ok(())
90}More examples
45fn main() -> Result<(), Box<dyn std::error::Error>> {
46 println!("=== Observable Property Basic Example ===\n");
47
48 // Create a person
49 let person = Person::new("Alice".to_string(), 25);
50
51 // Subscribe to name changes
52 let name_observer_id = person.name.subscribe(Arc::new(|old_name, new_name| {
53 println!("📝 Name changed: '{}' → '{}'", old_name, new_name);
54 }))?;
55
56 // Subscribe to age changes
57 let age_observer_id = person.age.subscribe(Arc::new(|old_age, new_age| {
58 println!("🎂 Age changed: {} → {}", old_age, new_age);
59 }))?;
60
61 // Subscribe to only significant age changes (milestones)
62 let milestone_observer_id = person.age.subscribe_filtered(
63 Arc::new(|_old_age, new_age| {
64 println!("🎉 Milestone reached! {} is now a special age: {}",
65 if *new_age >= 18 { "Adult" } else { "Child" }, new_age);
66 }),
67 |old_age, new_age| {
68 // Notify on milestone ages
69 let milestones = [18, 21, 30, 40, 50, 65];
70 milestones.contains(new_age) ||
71 (milestones.contains(old_age) && !milestones.contains(new_age))
72 }
73 )?;
74
75 println!("Initial state:");
76 println!(" Name: {}", person.get_name()?);
77 println!(" Age: {}\n", person.get_age()?);
78
79 // Demonstrate property changes
80 println!("Making changes...\n");
81
82 // Change name
83 person.set_name("Alice Johnson".to_string())?;
84
85 // Age up a few times
86 person.celebrate_birthday()?;
87 person.celebrate_birthday()?;
88 person.celebrate_birthday()?;
89
90 // Change to milestone age
91 person.set_age(21)?;
92
93 // Direct property access
94 println!("\nDirect property access:");
95 let simple_property = ObservableProperty::new(100);
96
97 simple_property.subscribe(Arc::new(|old, new| {
98 println!("💰 Value changed: {} → {}", old, new);
99 }))?;
100
101 simple_property.set(200)?;
102 simple_property.set(150)?;
103
104 // Cleanup observers
105 person.name.unsubscribe(name_observer_id)?;
106 person.age.unsubscribe(age_observer_id)?;
107 person.age.unsubscribe(milestone_observer_id)?;
108
109 println!("\n✅ Example completed successfully!");
110 Ok(())
111}Sourcepub fn unsubscribe(&self, id: ObserverId) -> Result<bool, PropertyError>
pub fn unsubscribe(&self, id: ObserverId) -> Result<bool, PropertyError>
Removes an observer by its ID
§Arguments
id- The observer ID returned bysubscribe()
§Returns
Ok(bool) where true means the observer was found and removed,
false means no observer with that ID existed.
Returns Err(PropertyError) if the lock is poisoned.
§Examples
use observable_property::ObservableProperty;
use std::sync::Arc;
let property = ObservableProperty::new(0);
let id = property.subscribe(Arc::new(|_, _| {})).unwrap();
let was_removed = property.unsubscribe(id).unwrap();
assert!(was_removed); // Observer existed and was removed
let was_removed_again = property.unsubscribe(id).unwrap();
assert!(!was_removed_again); // Observer no longer existsExamples found in repository?
44fn main() -> Result<(), Box<dyn std::error::Error>> {
45 println!("=== Observable Property Multithreaded Person Example ===\n");
46
47 let person = Arc::new(Person::new("Bob".to_string(), 30));
48
49 // Subscribe to name changes
50 let name_observer_id = person.name.subscribe(Arc::new(|old_name, new_name| {
51 println!("📝 Name changed: '{}' → '{}'", old_name, new_name);
52 }))?;
53
54 // Subscribe to age changes
55 let age_observer_id = person.age.subscribe(Arc::new(|old_age, new_age| {
56 println!("🎂 Age changed: {} → {}", old_age, new_age);
57 }))?;
58
59 // Spawn threads to update name and age concurrently
60 let person_clone1 = person.clone();
61 let handle1 = thread::spawn(move || {
62 for i in 0..3 {
63 let new_name = format!("Bob #{}", i + 1);
64 person_clone1.set_name(new_name).unwrap();
65 thread::sleep(Duration::from_millis(50));
66 }
67 });
68
69 let person_clone2 = person.clone();
70 let handle2 = thread::spawn(move || {
71 for _ in 0..3 {
72 person_clone2.celebrate_birthday().unwrap();
73 thread::sleep(Duration::from_millis(30));
74 }
75 });
76
77 handle1.join().unwrap();
78 handle2.join().unwrap();
79
80 println!("\nFinal state:");
81 println!(" Name: {}", person.get_name()?);
82 println!(" Age: {}", person.get_age()?);
83
84 // Cleanup observers
85 person.name.unsubscribe(name_observer_id)?;
86 person.age.unsubscribe(age_observer_id)?;
87
88 println!("\n✅ Multithreaded Person example completed successfully!");
89 Ok(())
90}More examples
45fn main() -> Result<(), Box<dyn std::error::Error>> {
46 println!("=== Observable Property Basic Example ===\n");
47
48 // Create a person
49 let person = Person::new("Alice".to_string(), 25);
50
51 // Subscribe to name changes
52 let name_observer_id = person.name.subscribe(Arc::new(|old_name, new_name| {
53 println!("📝 Name changed: '{}' → '{}'", old_name, new_name);
54 }))?;
55
56 // Subscribe to age changes
57 let age_observer_id = person.age.subscribe(Arc::new(|old_age, new_age| {
58 println!("🎂 Age changed: {} → {}", old_age, new_age);
59 }))?;
60
61 // Subscribe to only significant age changes (milestones)
62 let milestone_observer_id = person.age.subscribe_filtered(
63 Arc::new(|_old_age, new_age| {
64 println!("🎉 Milestone reached! {} is now a special age: {}",
65 if *new_age >= 18 { "Adult" } else { "Child" }, new_age);
66 }),
67 |old_age, new_age| {
68 // Notify on milestone ages
69 let milestones = [18, 21, 30, 40, 50, 65];
70 milestones.contains(new_age) ||
71 (milestones.contains(old_age) && !milestones.contains(new_age))
72 }
73 )?;
74
75 println!("Initial state:");
76 println!(" Name: {}", person.get_name()?);
77 println!(" Age: {}\n", person.get_age()?);
78
79 // Demonstrate property changes
80 println!("Making changes...\n");
81
82 // Change name
83 person.set_name("Alice Johnson".to_string())?;
84
85 // Age up a few times
86 person.celebrate_birthday()?;
87 person.celebrate_birthday()?;
88 person.celebrate_birthday()?;
89
90 // Change to milestone age
91 person.set_age(21)?;
92
93 // Direct property access
94 println!("\nDirect property access:");
95 let simple_property = ObservableProperty::new(100);
96
97 simple_property.subscribe(Arc::new(|old, new| {
98 println!("💰 Value changed: {} → {}", old, new);
99 }))?;
100
101 simple_property.set(200)?;
102 simple_property.set(150)?;
103
104 // Cleanup observers
105 person.name.unsubscribe(name_observer_id)?;
106 person.age.unsubscribe(age_observer_id)?;
107 person.age.unsubscribe(milestone_observer_id)?;
108
109 println!("\n✅ Example completed successfully!");
110 Ok(())
111}Sourcepub fn subscribe_filtered<F>(
&self,
observer: Observer<T>,
filter: F,
) -> Result<ObserverId, PropertyError>
pub fn subscribe_filtered<F>( &self, observer: Observer<T>, filter: F, ) -> Result<ObserverId, PropertyError>
Subscribes an observer that only gets called when a filter condition is met
This is useful for observing only specific types of changes, such as when a value increases or crosses a threshold.
§Arguments
observer- The observer function to call when the filter passesfilter- A predicate function that receives(old_value, new_value)and returnsbool
§Returns
Ok(ObserverId) for the filtered observer, or Err(PropertyError) if the lock is poisoned.
§Examples
use observable_property::ObservableProperty;
use std::sync::Arc;
let property = ObservableProperty::new(0);
// Only notify when value increases
let id = property.subscribe_filtered(
Arc::new(|old, new| println!("Value increased: {} -> {}", old, new)),
|old, new| new > old
).unwrap();
property.set(10).unwrap(); // Triggers observer (0 -> 10)
property.set(5).unwrap(); // Does NOT trigger observer (10 -> 5)
property.set(15).unwrap(); // Triggers observer (5 -> 15)Examples found in repository?
45fn main() -> Result<(), Box<dyn std::error::Error>> {
46 println!("=== Observable Property Basic Example ===\n");
47
48 // Create a person
49 let person = Person::new("Alice".to_string(), 25);
50
51 // Subscribe to name changes
52 let name_observer_id = person.name.subscribe(Arc::new(|old_name, new_name| {
53 println!("📝 Name changed: '{}' → '{}'", old_name, new_name);
54 }))?;
55
56 // Subscribe to age changes
57 let age_observer_id = person.age.subscribe(Arc::new(|old_age, new_age| {
58 println!("🎂 Age changed: {} → {}", old_age, new_age);
59 }))?;
60
61 // Subscribe to only significant age changes (milestones)
62 let milestone_observer_id = person.age.subscribe_filtered(
63 Arc::new(|_old_age, new_age| {
64 println!("🎉 Milestone reached! {} is now a special age: {}",
65 if *new_age >= 18 { "Adult" } else { "Child" }, new_age);
66 }),
67 |old_age, new_age| {
68 // Notify on milestone ages
69 let milestones = [18, 21, 30, 40, 50, 65];
70 milestones.contains(new_age) ||
71 (milestones.contains(old_age) && !milestones.contains(new_age))
72 }
73 )?;
74
75 println!("Initial state:");
76 println!(" Name: {}", person.get_name()?);
77 println!(" Age: {}\n", person.get_age()?);
78
79 // Demonstrate property changes
80 println!("Making changes...\n");
81
82 // Change name
83 person.set_name("Alice Johnson".to_string())?;
84
85 // Age up a few times
86 person.celebrate_birthday()?;
87 person.celebrate_birthday()?;
88 person.celebrate_birthday()?;
89
90 // Change to milestone age
91 person.set_age(21)?;
92
93 // Direct property access
94 println!("\nDirect property access:");
95 let simple_property = ObservableProperty::new(100);
96
97 simple_property.subscribe(Arc::new(|old, new| {
98 println!("💰 Value changed: {} → {}", old, new);
99 }))?;
100
101 simple_property.set(200)?;
102 simple_property.set(150)?;
103
104 // Cleanup observers
105 person.name.unsubscribe(name_observer_id)?;
106 person.age.unsubscribe(age_observer_id)?;
107 person.age.unsubscribe(milestone_observer_id)?;
108
109 println!("\n✅ Example completed successfully!");
110 Ok(())
111}Trait Implementations§
Source§impl<T: Clone> Clone for ObservableProperty<T>
impl<T: Clone> Clone for ObservableProperty<T>
Source§fn clone(&self) -> Self
fn clone(&self) -> Self
Creates a new reference to the same observable property
This creates a new ObservableProperty instance that shares the same
underlying data with the original. Changes made through either instance
will be visible to observers subscribed through both instances.
§Examples
use observable_property::ObservableProperty;
use std::sync::Arc;
let property1 = ObservableProperty::new(42);
let property2 = property1.clone();
property2.subscribe(Arc::new(|old, new| {
println!("Observer on property2 saw change: {} -> {}", old, new);
})).unwrap();
// This change through property1 will trigger the observer on property2
property1.set(100).unwrap();1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more