{"id":20641877,"url":"https://github.com/rogerisk/python-oop-concepts","last_synced_at":"2026-04-18T22:31:54.819Z","repository":{"id":244964289,"uuid":"816772301","full_name":"RogerIsk/python-oop-concepts","owner":"RogerIsk","description":"Python tasks that concentrate around classes and their use","archived":false,"fork":false,"pushed_at":"2024-06-25T12:58:12.000Z","size":334,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-09T12:56:51.700Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RogerIsk.png","metadata":{"files":{"readme":"README-2.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-18T11:28:06.000Z","updated_at":"2024-06-25T12:58:15.000Z","dependencies_parsed_at":"2024-06-23T12:24:52.242Z","dependency_job_id":"dccfa888-223b-458a-b442-0b1ba6f477c0","html_url":"https://github.com/RogerIsk/python-oop-concepts","commit_stats":null,"previous_names":["rogerisk/python-oop-concepts"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/RogerIsk/python-oop-concepts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RogerIsk%2Fpython-oop-concepts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RogerIsk%2Fpython-oop-concepts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RogerIsk%2Fpython-oop-concepts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RogerIsk%2Fpython-oop-concepts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RogerIsk","download_url":"https://codeload.github.com/RogerIsk/python-oop-concepts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RogerIsk%2Fpython-oop-concepts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31987748,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T20:23:30.271Z","status":"ssl_error","status_checked_at":"2026-04-18T20:23:29.375Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-16T16:07:06.157Z","updated_at":"2026-04-18T22:31:54.790Z","avatar_url":"https://github.com/RogerIsk.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Encapsulation - Books and Authors\n\nIn this exercise, we'll be visiting encapsulation, along with composition. We'll be creating a few\nclasses as described below:\n\n\u003e **Hint:** Composition is the term used for a **HAS-A relationship** between classes.\n---\n\nTake a look at the diagram of the Book and the Author classes:\n\n![img.png](img.png)\n\n## Author Class\n\nYou should write the Author class as shown in the class diagram. The class is designed to model a\nbook's author. it contains:\n\n1. **Three private instance variables**: `name` (str), `email` (str), and `gender` (str of\n   either 'Male' or 'Female').;\n\n\u003e **Bonus:** Make _**gender**_ an **Enum** instead and add non-binary gender values as you will.\n\n2. **The constructor** to initialize the name, email and gender with the given\n   values `Author (str name, str email, str gender) {......}`\n\n3. **Public** methods to get and set attributes: `get_name()`, `get_email()`, `set_email()`, and `get_gender()`;\n\n\u003e **Hint:** (There are no methods to set **name** and **gender**, as these attributes cannot be\n\u003e changed). Thus, you can also mark them **final**.\n\n4. A `__str__(self)` method that returns **Author[name=?,email=?,gender=?]**, e.g., `Author\n   [name=Aloe Vera, email=isthisanemail@somewhere.com,gender=m]`.\n\n\u003e **Hint:** The __str__(self) method of a class is automatically used whenever turning the class instance\n\u003e into a string. It has a default way of displaying it, but by overriding it, you can achieve a different\n\u003e result.\n---\n\n## Book Class\n\n\nYou should write the Book class as shown in the class diagram. The class is designed to model a book\nwritten by an author. It contains:\n\n1. **Four private instance variables**: `_name` (str), `_author` (of the class Author you have just\n   created), `_price` (float), and `_qty` (int);\n\n2. The constructor:\n\n`Book (str _name, Author _author, float _price, int _qty=1) { ...... }`\\\n\n3. **Public methods** `get_name()`, `get_author()`, `get_price()`, `set_price()`, `get_qty()`, `set_qty()`\n   .\n\n4. A `__str__(self)` method that returns `Book[name=?,Author[name=?,email=?,gender=?],price=?,qty=?`. You\n   should **reuse** Author’s `__str__(self)` here.\n\n\u003e **Hint:** Take note that **both** **Book** and **Author** classes have a variable called `name`. However, it\n\u003e can be differentiated via the referencing instance. For a Book instance, say `a_book`, `a_book.name`\n\u003e refers to the name of the book; whereas for an Author's instance, say `au_author`, `an_author.name`\n\u003e refers to the name of the author. **There is no need (and it's not recommended)** to call the\n\u003e variables `book_name` and `author_name`.\n\n---\n\n## BookTest Class\n\nNow that both our Author and Book classes are created, it's time to use them!\n\nHead to the BookTest class. This class contains our **main method**.\n\nCreate a few instances of the Author class. They'll be printed on the console once you run the main\nmethod.\n\nIn one of the instances, we'll call the set_email() method to change the value of the email, and then\nwe'll print it again. See how the value of the email changes?\n\nYou should see a result similar to this:\n\n![img_2.png](img_2.png)\n\nNow you should also create books instances. Create a few of them and associate the previously\ncreated authors to them.\n\nIn one of the instances, we'll be changing the price and the quantity through their respective\nsetter methods. You can see how the changes will be stored in the object instance.\n\nYou should get a result similar to this:\n\n![img_3.png](img_3.png)\n\n---\n\n## Results\n\nWith this, you can see how we achieved encapsulation. We aggregated states (attributes) and behaviors (\nmethods) together in a single place: a class. You can see that each class created is responsible to\nmanage its state, and no one else but itself, through its methods. With encapsulation, we can indicate\nthat no other class should modify the state of a class, and outside classes should only do what a\ngiven class indicates it should do.\n\n## Extra:\nNow that you understand encapsulation a bit more, go back to our BookTest class and spot the\nfollowing lines of code:\n\n```py\nprint(\"Author's name is: \" + book3.get_author().get_name())\nprint(\"Author's email is: \" + book3.get_author().get_email())\n```\n\nYou see how we get the author's name and email? We have to navigate to the author's instance\nthat linked to the book and then retrieve them. Now, reflect about this:\n\n#### Does it make sense that the Book class can retrieve those values directly?\n\nThe answer is: **depends!** On what? On our requirements. Make the next question:\n\n#### Is this an attribute (name, email) that is commonly requested from outside classes that are using the Book class?\n\nIf the answer is **yes**, then it probably makes sense.\n\nThen, with no further due, you can put create new methods in the Book class and move\nthese lines to it. Then it should look like this:\n\n```py\nprint(\"Author's name is: \" + book3.get_author_name())\nprint(\"Author's email is: \" + book3.get_author_email())\n```\n\nBy doing this, we're adding more functionality to the Book class - one that is **within its\nscope** - to retrieve its own author's name and email.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frogerisk%2Fpython-oop-concepts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frogerisk%2Fpython-oop-concepts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frogerisk%2Fpython-oop-concepts/lists"}