From 3c3c5cf67b60cde025ea17d748b8704a4387e95a Mon Sep 17 00:00:00 2001 From: darkicewolf50 Date: Wed, 2 Apr 2025 15:37:00 -0600 Subject: [PATCH] finished ch18.1 --- Characteristics of OO Languages.md | 117 ++++++++++++++++++ ...hat allow for Values of Different Types.md | 1 + guessing_game/target/.rustc_info.json | 2 +- hello_cargo/target/.rustc_info.json | 2 +- 4 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 Trait Objects that allow for Values of Different Types.md diff --git a/Characteristics of OO Languages.md b/Characteristics of OO Languages.md index ac66e98..dec7bdc 100644 --- a/Characteristics of OO Languages.md +++ b/Characteristics of OO Languages.md @@ -58,3 +58,120 @@ pub struct AveragedCollection { 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 { + 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` instead of a `Vec` 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` and `Vec` 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) diff --git a/Trait Objects that allow for Values of Different Types.md b/Trait Objects that allow for Values of Different Types.md new file mode 100644 index 0000000..6d458b9 --- /dev/null +++ b/Trait Objects that allow for Values of Different Types.md @@ -0,0 +1 @@ +# Using Trait Objects That Allow for Values of Different Types diff --git a/guessing_game/target/.rustc_info.json b/guessing_game/target/.rustc_info.json index bff229b..5de487d 100644 --- a/guessing_game/target/.rustc_info.json +++ b/guessing_game/target/.rustc_info.json @@ -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":{}} \ No newline at end of file +{"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":{}} \ No newline at end of file diff --git a/hello_cargo/target/.rustc_info.json b/hello_cargo/target/.rustc_info.json index f1a1e44..8613401 100644 --- a/hello_cargo/target/.rustc_info.json +++ b/hello_cargo/target/.rustc_info.json @@ -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":{}} \ No newline at end of file +{"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":{}} \ No newline at end of file