mirror of
https://github.com/darkicewolf50/RustBrock.git
synced 2025-06-15 04:54:17 -06:00
finished ch18.1
This commit is contained in:
parent
dbdd3d8d07
commit
3c3c5cf67b
@ -58,3 +58,120 @@ pub struct AveragedCollection {
|
|||||||
average: f64,
|
average: f64,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This struct is marked `pub` os that other code can use it.
|
||||||
|
|
||||||
|
The fields within the struct remain private.
|
||||||
|
|
||||||
|
This is improtant becuase we want to ensure that whenever a value is added or removed from the lust, the average is also updated.
|
||||||
|
|
||||||
|
We accomplish this by implementing `add`, `remove` and `average` methods on the struct.
|
||||||
|
|
||||||
|
This is shown here
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl AveragedCollection {
|
||||||
|
pub fn add(&mut self, value: i32) {
|
||||||
|
self.list.push(value);
|
||||||
|
self.update_average();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove(&mut self) -> Option<i32> {
|
||||||
|
let result = self.list.pop();
|
||||||
|
match result {
|
||||||
|
Some(value) => {
|
||||||
|
self.update_average();
|
||||||
|
Some(value)
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn average(&self) -> f64 {
|
||||||
|
self.average
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_average(&mut self) {
|
||||||
|
let total: i32 = self.list.iter().sum();
|
||||||
|
self.average = total as f64 / self.list.len() as f64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The public methods, `add`, `remove` and `average` are the only ways to access or modify data in any instance of `AverageCollection`.
|
||||||
|
|
||||||
|
When an item is added or removed to `list`, using the associated method, the implementations of each call the private `update_average` method that handles updating the `average` field as well.
|
||||||
|
|
||||||
|
We leave the `list` and `average` fields private, so that there is no way for external code to add or remove items to or form the `list` field directly.
|
||||||
|
|
||||||
|
The `average` method returns the value in the `average` field, this allows for external code to read the `average` but not modify it.
|
||||||
|
|
||||||
|
Because we have encapsulated the impleentation details of `AveragedCollection`.
|
||||||
|
|
||||||
|
We can easily change aspects, such as the data structure, in the future.
|
||||||
|
|
||||||
|
For example, we could use a `HashSet<i32>` instead of a `Vec<i32>` for the `list` field.
|
||||||
|
|
||||||
|
As long as the signatures of the `add`, `remove`, and `average` public methods stay the same.
|
||||||
|
|
||||||
|
Code using `AveragedCollection` wouldn't need to change to order to compile.
|
||||||
|
|
||||||
|
If we made `list` public instead, this wouldn't necessarily be the case
|
||||||
|
|
||||||
|
`HashSet<i32>` and `Vec<i32>` have different methods for adding and removing items, so the external code would likely have to change if it were modifying `list` directly.
|
||||||
|
|
||||||
|
If encapsulation is a required aspect for a language to be considered object-oriented, then Rust meets that requirement.
|
||||||
|
|
||||||
|
The option to use `pub` or not for different parts of code enbalbes encapsulation of implementation details
|
||||||
|
|
||||||
|
## Inheritance as a type System and as Code Sharing
|
||||||
|
|
||||||
|
_Inheritance_ is a mechanism whereby an object can inherit elements from another obejct's definition, thus gaining the parent object's data and behavior without you having to define them again.
|
||||||
|
|
||||||
|
If a language must have inheritance to be an obejct-oriented, then Rust is not one.
|
||||||
|
|
||||||
|
There is no way to define a struct that inherits the parent struct fields and method implementations without using a macro.
|
||||||
|
|
||||||
|
However, if you are use to having this tool available, you cna use other solutions in Rust, depending on your reason for reaching for inheritance.
|
||||||
|
|
||||||
|
Yuo choose inheritance for main reasons.
|
||||||
|
|
||||||
|
Resue of code: you can implement particular behavior for one type, and ingeritance enables ou to reuse that implementation for a different type.
|
||||||
|
|
||||||
|
You can do this in a limited way in Rust ocde using default trait method implementations.
|
||||||
|
|
||||||
|
We saw this before with the default implemetnation of the `summarize` method on the `Summary` trait.
|
||||||
|
|
||||||
|
Any type implementing the `Summary` trait would have the `summarize` method available on it without any further code.
|
||||||
|
|
||||||
|
This is similar to a parent class having an implementation of the `summarize` method when we `implement` the `Summary` trait, which is similar to a child class overriding the implementation of a method inherited form a parent class.
|
||||||
|
|
||||||
|
The other resaon to use ingeritance relates to the type system: to enable a child to be used in the same place as the parent type.
|
||||||
|
|
||||||
|
This has another name _polymorphism_, which means that you can substitute multiple objects for each other at runtime if they share certain characteristics.
|
||||||
|
|
||||||
|
### Polymorphism
|
||||||
|
|
||||||
|
To many this is synonymous with inheritance.
|
||||||
|
|
||||||
|
But it is actually a more general concept that refers to code that can work with data of multiple tpyes.
|
||||||
|
|
||||||
|
For inheritance, those types are generally subclasses.
|
||||||
|
|
||||||
|
Rust instead use generics to abstract over different possible types and trait bounds to impose constraints on what those tpyes must provide.
|
||||||
|
|
||||||
|
This is sometimes called *bounded parametric polymorphism*.
|
||||||
|
|
||||||
|
Inheritance has recently fallen out of favor as a programming deisgn solution, becuase it is often at risk of sharing more code than necessary.
|
||||||
|
|
||||||
|
Subclasses shouldn't always share all characteristics of thier parent class but will do so with inheritance.
|
||||||
|
|
||||||
|
This can make a program's design less flexible.
|
||||||
|
|
||||||
|
This also introduces the possibility of calling methods on subclasses that don't make sense or that cause errors because the methods don't apply to the subclass.
|
||||||
|
|
||||||
|
Additionally some languages will only allow single inheritance, meaning a subclass can only inherit from one class, thus further restricting the flexibility of a program's design.
|
||||||
|
|
||||||
|
These reasons are why Rust takes the different approach of using trait objects instead of inheritance.
|
||||||
|
|
||||||
|
Next lets see how trait obejcts enable polymorphism in Rust. [Here](./Trait%20Objects%20that%20allow%20for%20Values%20of%20Different%20Types.md)
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
# Using Trait Objects That Allow for Values of Different Types
|
@ -1 +1 @@
|
|||||||
{"rustc_fingerprint":953660965870803700,"outputs":{"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.85.1 (4eb161250 2025-03-15)\nbinary: rustc\ncommit-hash: 4eb161250e340c8f48f66e2b929ef4a5bed7c181\ncommit-date: 2025-03-15\nhost: x86_64-unknown-linux-gnu\nrelease: 1.85.1\nLLVM version: 19.1.7\n","stderr":""},"2063776225603076451":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/brock/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""},"13331785392996375709":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/brock/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}}
|
{"rustc_fingerprint":953660965870803700,"outputs":{"13331785392996375709":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/brock/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""},"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.85.1 (4eb161250 2025-03-15)\nbinary: rustc\ncommit-hash: 4eb161250e340c8f48f66e2b929ef4a5bed7c181\ncommit-date: 2025-03-15\nhost: x86_64-unknown-linux-gnu\nrelease: 1.85.1\nLLVM version: 19.1.7\n","stderr":""},"2063776225603076451":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/brock/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}}
|
@ -1 +1 @@
|
|||||||
{"rustc_fingerprint":953660965870803700,"outputs":{"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.85.1 (4eb161250 2025-03-15)\nbinary: rustc\ncommit-hash: 4eb161250e340c8f48f66e2b929ef4a5bed7c181\ncommit-date: 2025-03-15\nhost: x86_64-unknown-linux-gnu\nrelease: 1.85.1\nLLVM version: 19.1.7\n","stderr":""},"13331785392996375709":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/brock/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""},"2063776225603076451":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/brock/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}}
|
{"rustc_fingerprint":953660965870803700,"outputs":{"13331785392996375709":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/brock/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""},"2063776225603076451":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/brock/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""},"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.85.1 (4eb161250 2025-03-15)\nbinary: rustc\ncommit-hash: 4eb161250e340c8f48f66e2b929ef4a5bed7c181\ncommit-date: 2025-03-15\nhost: x86_64-unknown-linux-gnu\nrelease: 1.85.1\nLLVM version: 19.1.7\n","stderr":""}},"successes":{}}
|
Loading…
x
Reference in New Issue
Block a user