From 089fa0581dd928c64f14537db9841c27bf0e6973 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Wed, 21 Sep 2022 19:32:35 +0200 Subject: [PATCH 01/17] [RB129] Study Guide for Test --- RB120/RB129/test/study_guide.md | 56 +++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 RB120/RB129/test/study_guide.md diff --git a/RB120/RB129/test/study_guide.md b/RB120/RB129/test/study_guide.md new file mode 100644 index 0000000..9bf34d2 --- /dev/null +++ b/RB120/RB129/test/study_guide.md @@ -0,0 +1,56 @@ +# Study Guide for Test + +## Specific Topics of Interest + +- Classes and objects +- Use `attr_*` to create setter and getter methods +- How to call setters and getters +- Instance variables, class variables, and constants, including the scope of each type and how inheritance can affect that scope +- Instance methods vs. class methods +- Method Access Control +- Referencing and setting instance variables vs. using getters and setters +- Class inheritance, encapsulation, and polymorphism +- Modules +- Method lookup path +- self + - Calling methods with self + - More about self +- Reading OO code +- Fake operators and equality +- Working with collaborator objects + +## Precision of Language + +Some questions require that you explain code or concepts with words. It's important to explain how code works using precise vocabulary and to pinpoint the causal mechanism at work. In other words, use the right words and don't be vague. + +For example, let's take the following piece of code. + +```ruby +class Dog + def initialize(name) + @name = name + end + + def say_hello + puts "Woof! My name is #{@name}." + end +end +``` + +If we ask you to describe this code, you may say that "It defines a Dog class with two methods: an initializer and a method that has a message as a result." This description isn't wrong, but it's imprecise and lacks some essential details. An answer like this may receive a score of 5/10 on a 10-point question; 50% is not a passing score. + +A more precise answer says that "This code defines a Dog class with two methods: + +- The `#initialize` method that initializes a new `Dog` object, which it does by assigning the instance variable `@name` to the dog's name specified by the argument. +- The `#say_hello` instance method which prints a message that includes the dog's name in place of `#{@name}`. `#say_hello` returns `nil`." + + +In programming, we must always concern ourselves with outputs, return value, and object mutations. We must use the right terms when we speak, and not use vague words like "results." Furthermore, we need to be explicit about even the smallest details. + +When writing answers to test questions, make sure you're as precise as possible, and that you use the proper vocabulary. Doing this helps you debug and understand more complex code later in your journey. If your definitions are imprecise, you can't use them to decompose a complicated method or program. Also, you may be unable to pass the test. + +## Additional Tips + +This assessment has a different style than the RB109 written assessment,so you should expect several open-ended questions where you will need to explain certain OOP concepts using code examples. + +While working through the assessment questions it is useful to run your code often to check it, so make sure to have either ruby document/terminal or an online repl prepared beforehand. From 3a57f56fc5a3c40db3617e99590001d9814ed016 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Wed, 21 Sep 2022 21:01:00 +0200 Subject: [PATCH 02/17] [RB129] Update ruby version --- .ruby-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ruby-version b/.ruby-version index 849c0c4..49cdd66 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -ruby-2.7.5 +2.7.6 From ae8d37cd56a8ccc6d7c025c4caec3860ecd87334 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Wed, 21 Sep 2022 21:01:39 +0200 Subject: [PATCH 03/17] fixup! [RB129] Study Guide for Test --- RB120/RB129/test/study_guide.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/RB120/RB129/test/study_guide.md b/RB120/RB129/test/study_guide.md index 9bf34d2..bfa0e54 100644 --- a/RB120/RB129/test/study_guide.md +++ b/RB120/RB129/test/study_guide.md @@ -12,9 +12,7 @@ - Class inheritance, encapsulation, and polymorphism - Modules - Method lookup path -- self - - Calling methods with self - - More about self +- `self` - Reading OO code - Fake operators and equality - Working with collaborator objects From a4cd098a72d74c79bbcb045b77ba9138028f3ded Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Wed, 21 Sep 2022 21:01:47 +0200 Subject: [PATCH 04/17] [RB129] Classes and objects --- RB120/RB129/test/classes_and_objects.md | 48 +++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 RB120/RB129/test/classes_and_objects.md diff --git a/RB120/RB129/test/classes_and_objects.md b/RB120/RB129/test/classes_and_objects.md new file mode 100644 index 0000000..a6e8e6f --- /dev/null +++ b/RB120/RB129/test/classes_and_objects.md @@ -0,0 +1,48 @@ +# Classes and objects + +An object is an instance of a class. + +Objects are created from classes, so let's define classes first. + +## Classes + + +Classes are templates from which objects are created. Classes define what state and behavior objects can have. + +Objects are instances of a class. The process of creating a new object or instance from a class is called instantiation. Individual objects of the same class can contain different state. + +Classes are defined in Ruby using the `class` keyword followed by a name. The name must begin with a capital letter and by convention we use the CamelCase naming convention. The class definition is terminated by the `end` keyword. + +Objects are instantiated in Ruby by calling `new` on a class. Whenever a new object of a class is created using the `new` method, Ruby looks for a method named `initialize` and, if the method is found, it is called on the newly created object with the arguments that were passed to the `new` method. + +```ruby +class Greeter + def greet + puts "Hello! What is your name?" + end +end + +greeter1 = Greeter.new('John') +greeter1.greet # => Hello! What is your name? + +greeter2 = Greeter.new('Doe') +greeter2.greet # => Hello! What is your name? +``` + +```ruby +class Greeter + def initialize(name) + @name = name + end + + def greet + puts "Hello! My name is #{@name}. What is your name?" + end +end + +greeter1 = Greeter.new('John') +greeter1.greet # => Hello! My name is John. What is your name? + +greeter2 = Greeter.new('Doe') +greeter2.greet # => Hello! My name is Doe. What is your name? +``` From f440b4ad8a97b812298c2bec8df8a904d221d4c2 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Thu, 22 Sep 2022 18:05:57 +0200 Subject: [PATCH 05/17] fixup! [RB129] Classes and objects --- RB120/RB129/test/classes_and_objects.md | 32 +++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/RB120/RB129/test/classes_and_objects.md b/RB120/RB129/test/classes_and_objects.md index a6e8e6f..c85e398 100644 --- a/RB120/RB129/test/classes_and_objects.md +++ b/RB120/RB129/test/classes_and_objects.md @@ -13,7 +13,7 @@ Objects are instances of a class. The process of creating a new object or instan Classes are defined in Ruby using the `class` keyword followed by a name. The name must begin with a capital letter and by convention we use the CamelCase naming convention. The class definition is terminated by the `end` keyword. -Objects are instantiated in Ruby by calling `new` on a class. Whenever a new object of a class is created using the `new` method, Ruby looks for a method named `initialize` and, if the method is found, it is called on the newly created object with the arguments that were passed to the `new` method. +Objects are instantiated in Ruby by calling `#new` on a class. Whenever a new object of a class is created using the `#new` method, Ruby looks for a method named `#initialize` and, if found, it is called on the newly created object with the arguments that were passed to the `#new` method. ```ruby class Greeter @@ -22,13 +22,21 @@ class Greeter end end -greeter1 = Greeter.new('John') -greeter1.greet # => Hello! What is your name? +greeter1 = Greeter.new +greeter1.greet -greeter2 = Greeter.new('Doe') -greeter2.greet # => Hello! What is your name? +greeter2 = Greeter.new +greeter2.greet ``` +The above code defines a `Greeter` class with one method `#greet` that outputs the string `"Hello! What is your name?"` and returns `nil`. + +Next, an instance of the class `Greeter` is created by calling `Greeter.new` with no arguments and assigned to the local variable `greeter1`. The method `greet` is called on the `greeter1` which outputs the string `Hello! What is your name?` and returns `nil`. + +Next, another instance of the class `Greeter` is created by calling `Greeter.new` with no arguments and assigned to the local variable `greeter2`. The method `greet` is called on the `greeter2` which outputs the string `Hello! What is your name?` and returns `nil`. + +Since the class `Greeter` does not define any attributes and the method `greet` outputs a string with the same value every time, the objects created hold no differentiated state and share the exact same behavior. + ```ruby class Greeter def initialize(name) @@ -41,8 +49,18 @@ class Greeter end greeter1 = Greeter.new('John') -greeter1.greet # => Hello! My name is John. What is your name? +greeter1.greet greeter2 = Greeter.new('Doe') -greeter2.greet # => Hello! My name is Doe. What is your name? +greeter2.greet ``` + +The above code defines a `Greeter` class with two methods: +- The `#initialize` method, which is always called during the initialization process, is defined with one required parameter `name`. The value of `name` is assigned to the instance variable `@name`. +- The `#greet` method that outputs the string `"Hello! My name is #{@name}. What is your name?"`, where `#{@name}` will be replaced by the value returned by `@name.to_s`. `#greet` returns `nil`. + +Next, an instance of the class `Greeter` is created by calling `Greeter.new` with the argument `"John"` and assigned to the local variable `greeter1`. The method `greet` is called on the `greeter1` which outputs the string `Hello! My name is John. What is your name?` and returns `nil`. + +Next, another instance of the class `Greeter` is created by calling `Greeter.new` with the argument `"Doe"` and assigned to the local variable `greeter2`. The method `greet` is called on the `greeter2` which outputs the string `Hello! My name is Doe. What is your name?` and returns `nil`. + +Since the class `Greeter` defines a attribute `@name` and the method `greet` operates on that attribute, the objects created hold unique state and behavior from one another. From 63ac3a1eb977380a2f999a2894f4aac63cf98e14 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Thu, 22 Sep 2022 18:09:07 +0200 Subject: [PATCH 06/17] fixup! [RB129] Classes and objects --- RB120/RB129/test/classes_and_objects.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/RB120/RB129/test/classes_and_objects.md b/RB120/RB129/test/classes_and_objects.md index c85e398..1c25e95 100644 --- a/RB120/RB129/test/classes_and_objects.md +++ b/RB120/RB129/test/classes_and_objects.md @@ -6,7 +6,6 @@ Objects are created from classes, so let's define classes first. ## Classes - Classes are templates from which objects are created. Classes define what state and behavior objects can have. Objects are instances of a class. The process of creating a new object or instance from a class is called instantiation. Individual objects of the same class can contain different state. @@ -31,11 +30,11 @@ greeter2.greet The above code defines a `Greeter` class with one method `#greet` that outputs the string `"Hello! What is your name?"` and returns `nil`. -Next, an instance of the class `Greeter` is created by calling `Greeter.new` with no arguments and assigned to the local variable `greeter1`. The method `greet` is called on the `greeter1` which outputs the string `Hello! What is your name?` and returns `nil`. +Next, an instance of the class `Greeter` is created by calling `Greeter.new` with no arguments and assigned to the local variable `greeter1`. The method `#greet` is called on the `greeter1` which outputs the string `"Hello! What is your name?"` and returns `nil`. -Next, another instance of the class `Greeter` is created by calling `Greeter.new` with no arguments and assigned to the local variable `greeter2`. The method `greet` is called on the `greeter2` which outputs the string `Hello! What is your name?` and returns `nil`. +Next, another instance of the class `Greeter` is created by calling `Greeter.new` with no arguments and assigned to the local variable `greeter2`. The method `#greet` is called on the `greeter2` which outputs the string `"Hello! What is your name?"` and returns `nil`. -Since the class `Greeter` does not define any attributes and the method `greet` outputs a string with the same value every time, the objects created hold no differentiated state and share the exact same behavior. +Since the class `Greeter` does not define any attributes and the method `#greet` outputs a string with the same value every time, the objects created hold no differentiated state and share the exact same behavior. ```ruby class Greeter @@ -59,8 +58,8 @@ The above code defines a `Greeter` class with two methods: - The `#initialize` method, which is always called during the initialization process, is defined with one required parameter `name`. The value of `name` is assigned to the instance variable `@name`. - The `#greet` method that outputs the string `"Hello! My name is #{@name}. What is your name?"`, where `#{@name}` will be replaced by the value returned by `@name.to_s`. `#greet` returns `nil`. -Next, an instance of the class `Greeter` is created by calling `Greeter.new` with the argument `"John"` and assigned to the local variable `greeter1`. The method `greet` is called on the `greeter1` which outputs the string `Hello! My name is John. What is your name?` and returns `nil`. +Next, an instance of the class `Greeter` is created by calling `Greeter.new` with the argument `"John"` and assigned to the local variable `greeter1`. The method `#greet` is called on the `greeter1` which outputs the string `"Hello! My name is John. What is your name?"` and returns `nil`. -Next, another instance of the class `Greeter` is created by calling `Greeter.new` with the argument `"Doe"` and assigned to the local variable `greeter2`. The method `greet` is called on the `greeter2` which outputs the string `Hello! My name is Doe. What is your name?` and returns `nil`. +Next, another instance of the class `Greeter` is created by calling `Greeter.new` with the argument `"Doe"` and assigned to the local variable `greeter2`. The method `#greet` is called on the `greeter2` which outputs the string `"Hello! My name is Doe. What is your name?"` and returns `nil`. -Since the class `Greeter` defines a attribute `@name` and the method `greet` operates on that attribute, the objects created hold unique state and behavior from one another. +Since the class `Greeter` defines a attribute `@name` and the method `#greet` operates on that attribute, the objects created hold unique state and behavior from one another. From d7b73cfe7468ef39eee1348d312d11fc716ce4d1 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Thu, 22 Sep 2022 18:10:48 +0200 Subject: [PATCH 07/17] fixup! [RB129] Classes and objects --- RB120/RB129/test/study_guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RB120/RB129/test/study_guide.md b/RB120/RB129/test/study_guide.md index bfa0e54..ae93e23 100644 --- a/RB120/RB129/test/study_guide.md +++ b/RB120/RB129/test/study_guide.md @@ -2,7 +2,7 @@ ## Specific Topics of Interest -- Classes and objects +- [Classes and objects](./classes_and_objects.md) - Use `attr_*` to create setter and getter methods - How to call setters and getters - Instance variables, class variables, and constants, including the scope of each type and how inheritance can affect that scope From 7e19e08f56f8c74ed76b8383c096cefc84d8c7d3 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Fri, 23 Sep 2022 18:16:10 +0200 Subject: [PATCH 08/17] fixup! [RB129] Classes and objects --- RB120/RB129/test/classes_and_objects.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/RB120/RB129/test/classes_and_objects.md b/RB120/RB129/test/classes_and_objects.md index 1c25e95..1eb3901 100644 --- a/RB120/RB129/test/classes_and_objects.md +++ b/RB120/RB129/test/classes_and_objects.md @@ -1,11 +1,5 @@ # Classes and objects -An object is an instance of a class. - -Objects are created from classes, so let's define classes first. - -## Classes - Classes are templates from which objects are created. Classes define what state and behavior objects can have. Objects are instances of a class. The process of creating a new object or instance from a class is called instantiation. Individual objects of the same class can contain different state. From 4e85d4b6de192db9312ea5807c3e1f50d6a7938a Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Fri, 23 Sep 2022 19:22:08 +0200 Subject: [PATCH 09/17] [RB129] Use `attr_*` to create setter and getter methods --- RB120/RB129/test/attr_accessor_methods.md | 72 +++++++++++++++++++++++ RB120/RB129/test/study_guide.md | 2 +- 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 RB120/RB129/test/attr_accessor_methods.md diff --git a/RB120/RB129/test/attr_accessor_methods.md b/RB120/RB129/test/attr_accessor_methods.md new file mode 100644 index 0000000..ef95a62 --- /dev/null +++ b/RB120/RB129/test/attr_accessor_methods.md @@ -0,0 +1,72 @@ +# Use `attr_*` to create setter and getter methods + +Setter ad getter methods are methods used to set or get an attribute (instance variable) of an object. + +```ruby +class Dog + def set_breed=(breed) + @breed = breed + end + + def get_breed + @breed + end +end + +dog = Dog.new +dog.set_breed = 'Dalmatian' +dog.get_breed +``` + +In the code above, a `Dog` class is defined with two methods: +- The `#set_breed=` method is defined with one required parameter `breed`. The value referenced by `breed` is assigned to the instance variable `@breed`. Because the method name ends in `=`, Ruby allows us to use the assignment syntax when calling the method: `object.set_breed = breed` instead of `object.set_breed=(breed)`. Also, when it comes to the return value, the same rules as in regular assignment apply: the right-hand value is always returned no matter what the body of the method returns. +- The `#set_breed` method which returns the value of the instance variable `@breed`. Because the method retrieves some state of the object, it acts as a getter method. + +Next, an instance of the class `Dog` is created by calling `Greeter.new` with no arguments and assigned to the local variable `dog`. Then, the method `#set_breed=` is called on the object referenced by `dog` which the argument `"Dalmatian"` which makes the instance variable `@breed` to point to the argument. Then, the method `#set_breed` is called on the object referenced by `dog` which returns the string `"Dalmatian"`. + +Because the method `set_breed=` allows to change the value of an attribute to be the value passed as argument, it is considered a setter method. Because the method `set_breed` allows to retrieve the value of an attribute, it is considered a getter method. In Ruby, however, the convention is to name getter and setter methods using the same name as the instance variable they are exposing and setting. Thus, we could refactor the code as follows: + +```ruby +class Dog + def breed=(breed) + @breed = breed + end + + def breed + @breed + end +end + +dog = Dog.new +dog.breed = 'Dalmatian' +dog.breed +``` + +Because these methods are so commonplace, Ruby has a built-in way to automatically create these getter and setter methods for us, using the `attr_accessor` method. Thus, we could refactor the code as follows: + +```ruby +class Dog + attr_accessor :breed +end + +dog = Dog.new +dog.breed = 'Dalmatian' +dog.breed +``` + +The `attr_accessor` method defines a setter and a getter method for each argument that was passed. Besides the `attr_accessor` method, we have two more methods to automatically define getter and setter methods: +- The `attr_writer` method which only defines a setter method. +- The `attr_reader` method which only defines a getter method. + +Thus, we could refactor the code as follows: + +```ruby +class Dog + attr_writer :breed + attr_reader :breed +end + +dog = Dog.new +dog.breed = 'Dalmatian' +dog.breed +``` diff --git a/RB120/RB129/test/study_guide.md b/RB120/RB129/test/study_guide.md index ae93e23..e1b22f3 100644 --- a/RB120/RB129/test/study_guide.md +++ b/RB120/RB129/test/study_guide.md @@ -3,7 +3,7 @@ ## Specific Topics of Interest - [Classes and objects](./classes_and_objects.md) -- Use `attr_*` to create setter and getter methods +- [Use `attr_*` to create setter and getter methods](./attr_accessor_methods.md) - How to call setters and getters - Instance variables, class variables, and constants, including the scope of each type and how inheritance can affect that scope - Instance methods vs. class methods From 9a8d113d86cdbb70475b94c20f4bb12b081ac007 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Sat, 24 Sep 2022 10:55:24 +0200 Subject: [PATCH 10/17] =?UTF-8?q?=CC=80[RB129]=20How=20to=20call=20setters?= =?UTF-8?q?=20and=20getters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...r_accessor_methods.md => getter_and_setter_methods.md} | 8 ++++---- RB120/RB129/test/study_guide.md | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) rename RB120/RB129/test/{attr_accessor_methods.md => getter_and_setter_methods.md} (85%) diff --git a/RB120/RB129/test/attr_accessor_methods.md b/RB120/RB129/test/getter_and_setter_methods.md similarity index 85% rename from RB120/RB129/test/attr_accessor_methods.md rename to RB120/RB129/test/getter_and_setter_methods.md index ef95a62..30690fc 100644 --- a/RB120/RB129/test/attr_accessor_methods.md +++ b/RB120/RB129/test/getter_and_setter_methods.md @@ -1,6 +1,6 @@ -# Use `attr_*` to create setter and getter methods +# Setter and getter methods -Setter ad getter methods are methods used to set or get an attribute (instance variable) of an object. +Setter and getter methods are methods used to set or get the state of an object. ```ruby class Dog @@ -20,7 +20,7 @@ dog.get_breed In the code above, a `Dog` class is defined with two methods: - The `#set_breed=` method is defined with one required parameter `breed`. The value referenced by `breed` is assigned to the instance variable `@breed`. Because the method name ends in `=`, Ruby allows us to use the assignment syntax when calling the method: `object.set_breed = breed` instead of `object.set_breed=(breed)`. Also, when it comes to the return value, the same rules as in regular assignment apply: the right-hand value is always returned no matter what the body of the method returns. -- The `#set_breed` method which returns the value of the instance variable `@breed`. Because the method retrieves some state of the object, it acts as a getter method. +- The `#set_breed` method which returns the value of the instance variable `@breed`. Next, an instance of the class `Dog` is created by calling `Greeter.new` with no arguments and assigned to the local variable `dog`. Then, the method `#set_breed=` is called on the object referenced by `dog` which the argument `"Dalmatian"` which makes the instance variable `@breed` to point to the argument. Then, the method `#set_breed` is called on the object referenced by `dog` which returns the string `"Dalmatian"`. @@ -54,7 +54,7 @@ dog.breed = 'Dalmatian' dog.breed ``` -The `attr_accessor` method defines a setter and a getter method for each argument that was passed. Besides the `attr_accessor` method, we have two more methods to automatically define getter and setter methods: +The `attr_accessor` method defines a setter and a getter method names as the argument, for each argument that was passed. Besides the `attr_accessor` method, we have two more methods to automatically define getter and setter methods: - The `attr_writer` method which only defines a setter method. - The `attr_reader` method which only defines a getter method. diff --git a/RB120/RB129/test/study_guide.md b/RB120/RB129/test/study_guide.md index e1b22f3..27e34ae 100644 --- a/RB120/RB129/test/study_guide.md +++ b/RB120/RB129/test/study_guide.md @@ -3,8 +3,8 @@ ## Specific Topics of Interest - [Classes and objects](./classes_and_objects.md) -- [Use `attr_*` to create setter and getter methods](./attr_accessor_methods.md) -- How to call setters and getters +- [Use `attr_*` to create setter and getter methods](./getter_and_setter_methods.md) +- [How to call setters and getters](./getter_and_setter_methods.md) - Instance variables, class variables, and constants, including the scope of each type and how inheritance can affect that scope - Instance methods vs. class methods - Method Access Control From a24b21d54b76ae1c813f5eed8ffb71405c2ee8c9 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Sun, 25 Sep 2022 15:46:29 +0200 Subject: [PATCH 11/17] [RB129] Reorganize code --- .../test/classes_and_objects.md | 12 ++--- .../how_to_call_getter_and_setter_methods.md | 45 +++++++++++++++++++ .../instance_class_and_constant_variables.md | 9 ++++ {RB120/RB129 => RB129}/test/study_guide.md | 2 +- ...ttr_to_create_setter_and_getter_methods.md | 12 ++--- 5 files changed, 68 insertions(+), 12 deletions(-) rename {RB120/RB129 => RB129}/test/classes_and_objects.md (77%) create mode 100644 RB129/test/how_to_call_getter_and_setter_methods.md create mode 100644 RB129/test/instance_class_and_constant_variables.md rename {RB120/RB129 => RB129}/test/study_guide.md (94%) rename RB120/RB129/test/getter_and_setter_methods.md => RB129/test/use_attr_to_create_setter_and_getter_methods.md (58%) diff --git a/RB120/RB129/test/classes_and_objects.md b/RB129/test/classes_and_objects.md similarity index 77% rename from RB120/RB129/test/classes_and_objects.md rename to RB129/test/classes_and_objects.md index 1eb3901..19a7b0e 100644 --- a/RB120/RB129/test/classes_and_objects.md +++ b/RB129/test/classes_and_objects.md @@ -1,12 +1,14 @@ # Classes and objects -Classes are templates from which objects are created. Classes define what state and behavior objects can have. +Classes are templates from which objects are created. Classes define what states and behavior objects can have: +- States track information for individual objects and are implemented in Ruby via instance variables. +- Behaviors are what objects are capable of doing and are implemented in Ruby via instance methods. -Objects are instances of a class. The process of creating a new object or instance from a class is called instantiation. Individual objects of the same class can contain different state. +Objects are instances of a class. The process of creating a new object or instance from a class is called instantiation. Individual objects of the same class can contain different state, but they all share the same behavior. Classes are defined in Ruby using the `class` keyword followed by a name. The name must begin with a capital letter and by convention we use the CamelCase naming convention. The class definition is terminated by the `end` keyword. -Objects are instantiated in Ruby by calling `#new` on a class. Whenever a new object of a class is created using the `#new` method, Ruby looks for a method named `#initialize` and, if found, it is called on the newly created object with the arguments that were passed to the `#new` method. +Objects are instantiated in Ruby by calling `#new` on a class. Whenever a new object of a class is created using the `#new` method, Ruby looks for a method named `#initialize` and, if found, it is called on the newly created object with the arguments that were passed to the `#new` method. We refer to the `#initialize` method as a constructor, because it is a special method that builds the object when a new object is instantiated. ```ruby class Greeter @@ -28,7 +30,7 @@ Next, an instance of the class `Greeter` is created by calling `Greeter.new` wit Next, another instance of the class `Greeter` is created by calling `Greeter.new` with no arguments and assigned to the local variable `greeter2`. The method `#greet` is called on the `greeter2` which outputs the string `"Hello! What is your name?"` and returns `nil`. -Since the class `Greeter` does not define any attributes and the method `#greet` outputs a string with the same value every time, the objects created hold no differentiated state and share the exact same behavior. +Since the class `Greeter` does not define any instance variables, the objects it can create do not hold unique state from one another. ```ruby class Greeter @@ -56,4 +58,4 @@ Next, an instance of the class `Greeter` is created by calling `Greeter.new` wit Next, another instance of the class `Greeter` is created by calling `Greeter.new` with the argument `"Doe"` and assigned to the local variable `greeter2`. The method `#greet` is called on the `greeter2` which outputs the string `"Hello! My name is Doe. What is your name?"` and returns `nil`. -Since the class `Greeter` defines a attribute `@name` and the method `#greet` operates on that attribute, the objects created hold unique state and behavior from one another. +Since the class `Greeter` defines an instance variable `@name`, the objects it can create can hold unique state from one another: different objects may have different names. diff --git a/RB129/test/how_to_call_getter_and_setter_methods.md b/RB129/test/how_to_call_getter_and_setter_methods.md new file mode 100644 index 0000000..71a037f --- /dev/null +++ b/RB129/test/how_to_call_getter_and_setter_methods.md @@ -0,0 +1,45 @@ +# How to call setters and getters + +Setter and getter methods are methods that change or expose the state of an object. + +```ruby +class Dog + attr_accessor :breed + + def reset_breed + self.breed = nil + end +end + +dog = Dog.new +dog.breed = 'Dalmatian' +dog.reset_breed +dog.breed +``` + +In the code above, a `Dog` class is defined with three methods: +- The `#breed=` setter method and the `#breed` getter method are defined automatically by calling `::attr_accessor` with the argument `:breed`. +- The `#reset_breed` method calls the setter method `#breed=` on `self` with the argument `nil`, assigning `nil` to the instance variable `@breed`. + +Next, an instance of the class `Dog` is created by calling `Greeter.new` with no arguments and assigned to the local variable `dog`. Then, the method `#breed=` is called on the object referenced by `dog` which the argument `"Dalmatian"` which makes the instance variable `@breed` to point to the argument. Then, the method `#reset_breed` is called on the object referenced by `dog` which assigns `nil` to the instance variable `@breed` and returns `nil`. Then, the method `#breed` is called on the object referenced by `dog` which returns the value of the instance variable `@breed`: `nil`. + +When it comes to calling a setter method inside a class definition, because Ruby allows us to use the assignment syntax when calling a setter method: `dog.breed = 'Dalmatian'` instead of `dog.breed=('Dalmatian')`, it is needed to use `self` to disimbiguate from creating a local variable. + +If instead we define the class as follows: + +```ruby +class Dog + attr_accessor :breed + + def reset_breed + breed = nil + end +end + +dog = Dog.new +dog.breed = 'Dalmatian' +dog.reset_breed +dog.breed +``` + +We will find that the last line `dog.breed` returns the string `"Dalmatian"`, instead of `nil`. This is because in the body of the `#reset_breed` method, instead of a call to the `#breed=` method, a local variable assignment is taking place `breed = nil`. diff --git a/RB129/test/instance_class_and_constant_variables.md b/RB129/test/instance_class_and_constant_variables.md new file mode 100644 index 0000000..8ce9e64 --- /dev/null +++ b/RB129/test/instance_class_and_constant_variables.md @@ -0,0 +1,9 @@ +# Instance variables, class variables, and constants, including the scope of each type and how inheritance can affect that scope + +Instance variables are defined starting with a `@` symbol. Instance variables are scoped to the object level, meaning it can be referenced from anywhere + +This should tell you that instance variables are scoped at the object (or instance) level, and are how objects keep track of their states. + +```ruby +@Asdasd +``` diff --git a/RB120/RB129/test/study_guide.md b/RB129/test/study_guide.md similarity index 94% rename from RB120/RB129/test/study_guide.md rename to RB129/test/study_guide.md index 27e34ae..2e24534 100644 --- a/RB120/RB129/test/study_guide.md +++ b/RB129/test/study_guide.md @@ -5,7 +5,7 @@ - [Classes and objects](./classes_and_objects.md) - [Use `attr_*` to create setter and getter methods](./getter_and_setter_methods.md) - [How to call setters and getters](./getter_and_setter_methods.md) -- Instance variables, class variables, and constants, including the scope of each type and how inheritance can affect that scope +- [Instance variables, class variables, and constants, including the scope of each type and how inheritance can affect that scope](./instance_class_and_constant_variables.md) - Instance methods vs. class methods - Method Access Control - Referencing and setting instance variables vs. using getters and setters diff --git a/RB120/RB129/test/getter_and_setter_methods.md b/RB129/test/use_attr_to_create_setter_and_getter_methods.md similarity index 58% rename from RB120/RB129/test/getter_and_setter_methods.md rename to RB129/test/use_attr_to_create_setter_and_getter_methods.md index 30690fc..dbd02ff 100644 --- a/RB120/RB129/test/getter_and_setter_methods.md +++ b/RB129/test/use_attr_to_create_setter_and_getter_methods.md @@ -1,6 +1,6 @@ -# Setter and getter methods +# Use `attr_*` to create setter and getter methods -Setter and getter methods are methods used to set or get the state of an object. +Setter and getter methods are methods that change or expose the state of an object. ```ruby class Dog @@ -19,12 +19,12 @@ dog.get_breed ``` In the code above, a `Dog` class is defined with two methods: -- The `#set_breed=` method is defined with one required parameter `breed`. The value referenced by `breed` is assigned to the instance variable `@breed`. Because the method name ends in `=`, Ruby allows us to use the assignment syntax when calling the method: `object.set_breed = breed` instead of `object.set_breed=(breed)`. Also, when it comes to the return value, the same rules as in regular assignment apply: the right-hand value is always returned no matter what the body of the method returns. +- The `#set_breed=` method is defined with one required parameter `breed`. The value referenced by `breed` is assigned to the instance variable `@breed`. Because the method name ends in `=`, Ruby allows us to use the assignment syntax when calling the method: `object.set_breed = breed` instead of `object.set_breed=(breed)`. Also, because the method name ends in `=`, when it comes to the return value, the same rules as in assignment apply: the right-hand value is always returned no matter what the body of the method returns. - The `#set_breed` method which returns the value of the instance variable `@breed`. -Next, an instance of the class `Dog` is created by calling `Greeter.new` with no arguments and assigned to the local variable `dog`. Then, the method `#set_breed=` is called on the object referenced by `dog` which the argument `"Dalmatian"` which makes the instance variable `@breed` to point to the argument. Then, the method `#set_breed` is called on the object referenced by `dog` which returns the string `"Dalmatian"`. +Next, an instance of the class `Dog` is created by calling `Greeter.new` with no arguments and assigned to the local variable `dog`. Then, the method `#set_breed=` is called on the object referenced by `dog` which the argument `"Dalmatian"` which makes the instance variable `@breed` to point to the argument and returns the argument. Then, the method `#get_breed` is called on the object referenced by `dog` which returns the value of the instance variable `@breed`: `"Dalmatian"`. -Because the method `set_breed=` allows to change the value of an attribute to be the value passed as argument, it is considered a setter method. Because the method `set_breed` allows to retrieve the value of an attribute, it is considered a getter method. In Ruby, however, the convention is to name getter and setter methods using the same name as the instance variable they are exposing and setting. Thus, we could refactor the code as follows: +Because the method `set_breed=` allows to change the value of an instance variable to be the value passed as argument, it is considered a setter method. Because the method `get_breed` exposes the value of an instance variable, it is considered a getter method. In Ruby, however, the convention is to name getter and setter methods using the same name as the instance variable they are exposing and setting. Thus, we could refactor the code as follows: ```ruby class Dog @@ -54,7 +54,7 @@ dog.breed = 'Dalmatian' dog.breed ``` -The `attr_accessor` method defines a setter and a getter method names as the argument, for each argument that was passed. Besides the `attr_accessor` method, we have two more methods to automatically define getter and setter methods: +The `attr_accessor` method takes one or more string or symbol arguments, which it uses to create the method name for the getter and setter methods. Besides the `attr_accessor` method, we have two more methods to automatically define getter and setter methods: - The `attr_writer` method which only defines a setter method. - The `attr_reader` method which only defines a getter method. From 953030a7e0d547ed9b3b2d43aa5f072c3c3bba11 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Sun, 25 Sep 2022 23:21:31 +0200 Subject: [PATCH 12/17] [RB129] Instance variables --- RB129/test/classes_and_objects.md | 6 ++-- .../instance_class_and_constant_variables.md | 35 +++++++++++++++++-- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/RB129/test/classes_and_objects.md b/RB129/test/classes_and_objects.md index 19a7b0e..1717970 100644 --- a/RB129/test/classes_and_objects.md +++ b/RB129/test/classes_and_objects.md @@ -4,7 +4,7 @@ Classes are templates from which objects are created. Classes define what states - States track information for individual objects and are implemented in Ruby via instance variables. - Behaviors are what objects are capable of doing and are implemented in Ruby via instance methods. -Objects are instances of a class. The process of creating a new object or instance from a class is called instantiation. Individual objects of the same class can contain different state, but they all share the same behavior. +Objects are instances of a class. The process of creating a new object or instance from a class is called instantiation. Individual objects of the same class may contain different state, but they all share the same behavior. Classes are defined in Ruby using the `class` keyword followed by a name. The name must begin with a capital letter and by convention we use the CamelCase naming convention. The class definition is terminated by the `end` keyword. @@ -30,7 +30,7 @@ Next, an instance of the class `Greeter` is created by calling `Greeter.new` wit Next, another instance of the class `Greeter` is created by calling `Greeter.new` with no arguments and assigned to the local variable `greeter2`. The method `#greet` is called on the `greeter2` which outputs the string `"Hello! What is your name?"` and returns `nil`. -Since the class `Greeter` does not define any instance variables, the objects it can create do not hold unique state from one another. +Since the class `Greeter` does not define any instance variables, the objects it can create cannot hold different state from one another. ```ruby class Greeter @@ -58,4 +58,4 @@ Next, an instance of the class `Greeter` is created by calling `Greeter.new` wit Next, another instance of the class `Greeter` is created by calling `Greeter.new` with the argument `"Doe"` and assigned to the local variable `greeter2`. The method `#greet` is called on the `greeter2` which outputs the string `"Hello! My name is Doe. What is your name?"` and returns `nil`. -Since the class `Greeter` defines an instance variable `@name`, the objects it can create can hold unique state from one another: different objects may have different names. +Since the class `Greeter` defines an instance variable `@name`, the objects it can create can hold different state from one another: different objects may have different names. diff --git a/RB129/test/instance_class_and_constant_variables.md b/RB129/test/instance_class_and_constant_variables.md index 8ce9e64..703c6d7 100644 --- a/RB129/test/instance_class_and_constant_variables.md +++ b/RB129/test/instance_class_and_constant_variables.md @@ -1,9 +1,38 @@ # Instance variables, class variables, and constants, including the scope of each type and how inheritance can affect that scope -Instance variables are defined starting with a `@` symbol. Instance variables are scoped to the object level, meaning it can be referenced from anywhere +## Instance variables -This should tell you that instance variables are scoped at the object (or instance) level, and are how objects keep track of their states. +Instance variables are defined starting with a `@` symbol. They are used to track individual object state, and do not cross over between objects. + +For example, in the below code, the instance variable `@name` has a different value assigned inside each object. ```ruby -@Asdasd +class Person + attr_reader :name + + def initialize(n) + @name = n + end +end + +bob = Person.new('bob') +joe = Person.new('joe') + +bob.name # => "bob" +joe.name # => "joe" ``` + +Instance variables are scoped at the object level, meaning it can be referenced from any of an object's instance methods. In the example above, the instance variable `@name` is accessible in the instance method `#name` even though it was initialized inside the method `#initialize` and was not passed in as argument. + +If you try to reference an uninitialized local variable, you'd get a `NameError`. But if you try to reference an uninitialized instance variable, you get `nil`. + +```ruby +class Person + attr_accessor :name +end + +bob = Person.new +bob.name # => nil +``` + +## Class variables From 2452e665cbbd549a5b2d34d1200f2c9182735db3 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Sun, 2 Oct 2022 16:28:00 +0200 Subject: [PATCH 13/17] [RB129] Class variables and constants --- .../instance_class_and_constant_variables.md | 108 +++++++++++++++++- 1 file changed, 104 insertions(+), 4 deletions(-) diff --git a/RB129/test/instance_class_and_constant_variables.md b/RB129/test/instance_class_and_constant_variables.md index 703c6d7..e0c2a6e 100644 --- a/RB129/test/instance_class_and_constant_variables.md +++ b/RB129/test/instance_class_and_constant_variables.md @@ -2,9 +2,9 @@ ## Instance variables -Instance variables are defined starting with a `@` symbol. They are used to track individual object state, and do not cross over between objects. +Instance variables are defined starting with a `@` symbol like so: `@instance_variable`. They are used to track individual object state, and do not cross over between objects. -For example, in the below code, the instance variable `@name` has a different value assigned inside each object. +For example, in the below code, the instance variable `@name` has a different value assigned when referenced from each object. ```ruby class Person @@ -22,9 +22,9 @@ bob.name # => "bob" joe.name # => "joe" ``` -Instance variables are scoped at the object level, meaning it can be referenced from any of an object's instance methods. In the example above, the instance variable `@name` is accessible in the instance method `#name` even though it was initialized inside the method `#initialize` and was not passed in as argument. +Instance variables are scoped at the object level, meaning they can be referenced from any instance method. In the example above, the instance variable `@name` is accessible in the instance method `#name` even though it was initialized inside the method `#initialize` and was not passed in as argument. -If you try to reference an uninitialized local variable, you'd get a `NameError`. But if you try to reference an uninitialized instance variable, you get `nil`. +If you try to reference an uninitialized local variable, you'd get a a `NameError` exception exception. But if you try to reference an uninitialized instance variable, you get `nil`. ```ruby class Person @@ -36,3 +36,103 @@ bob.name # => nil ``` ## Class variables + +Class variables are defined starting with two `@` symbols like so: `@@class_variable`. They are used to track class state, and do cross over between objects. + +For example, in the below code, the class variable `@@number_of_persons` has the same value assigned when referenced from the class and each object. + +```ruby +class Person + @@number_of_persons = 0 + + def initialize(n) + @number_of_persons += 1 + end + + def number_of_persons_excluding_me + @@number_of_persons - 1 + end + + def self.number_of_persons + @@number_of_persons + end +end + +Person.number_of_persons # => 0 + +person1 = Person.new + +Person.number_of_persons # => 1 +person1.number_of_persons_excluding_me # => 0 + +person2 = Person.new + +Person.number_of_persons # => 2 +person2.number_of_persons_excluding_me # => 1 +``` + +Class variables are scoped at the class level, meaning they can be referenced from any class method or instance method. All objects from a class share the same the class variables. In the example above, the class variable `@@number_of_persons` is accessible in the instance methods `#initialize` and `#number_of_persons_excluding_me` even though it was initialized in the `Person` class definition and was not passed in as argument. + +Similarly to instance variables, if you try to reference an uninitialized class variable, you get `nil` instead of a a `NameError` exception exception. + +```ruby +class Person + def self.number_of_persons + @@number_of_persons + end +end + +Person.number_of_persons # => nil +``` + +## Constants + +Constants are defined starting with an upper case letter like so: `CONSTANT`. While technically constants just need to begin with a capital letter, the convention is to make the entire variable uppercase. They are used to track state that is not supposed to change. While technically constants can be reassigned and the object assigned to them can be mutated, best practices dictate not doing so. Ruby will throw a warning when reassigning a new value to constants but will not complain at all when mutating objects assigned to constants. + +For example, in the below code, the constant `DOG_YEARS` has the same value assigned when referenced from the class and each object. + +```ruby +class Dog + DOG_YEARS = 7 + + attr_accessor :age + + def initialize(age) + self.age = age + end + + def dog_years + age * DOG_YEARS + end + + def self.dog_years + DOG_YEARS + end +end + +dog1 = Dog.new(4) +dog2 = Dog.new(2) + +Dog.dog_years # => 7 +dog1.age # => 4 +dog1.age_in_dog_years # => 28 +dog2.age # => 2 +dog2.age_in_dog_years # => 14 +Dog::DOG_YEARS # => 7 +``` + +Constants have lexical scope, meaning that where the constant is defined in the source code determines where it is available. For a more in depth explanation of how constant variable scope works, [read this](../../RB120/lesson_3/constant_variable_scope.md). Unlike class or instance variables, constants initialized inside a module or a class (namespaced) can be reached from outside of the module or class using `::`, which is the namespace resolution operator. + +Unlike class and instance variables, if you try to reference an uninitialized constant, you get a `NameError` exception. + +```ruby +SOME_CONSTANT_THAT_DOES_NOT_EXIST # => NameError +``` + +Constants cannot be initialized inside a method (unless using metaprogramming), you get a `SyntaxError` exception. + +```ruby +def define_constant + PI = 3.14 +end # => SyntaxError (dynamic constant assignment) +``` From a1831e6a08d3a16dfd0c465c226f095b658fd3b0 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Wed, 12 Oct 2022 08:55:07 +0200 Subject: [PATCH 14/17] [RB129] Instance methods vs. class methods --- .ruby-version | 2 +- .../test/instance_methods_vs_class_methods.md | 25 +++++++++++++++++++ RB129/test/study_guide.md | 2 +- 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 RB129/test/instance_methods_vs_class_methods.md diff --git a/.ruby-version b/.ruby-version index 49cdd66..ef538c2 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.6 +3.1.2 diff --git a/RB129/test/instance_methods_vs_class_methods.md b/RB129/test/instance_methods_vs_class_methods.md new file mode 100644 index 0000000..482cbc7 --- /dev/null +++ b/RB129/test/instance_methods_vs_class_methods.md @@ -0,0 +1,25 @@ +# Instance methods vs. class methods + +## Instance methods + +Instance methods are methods defined inside a class definition. Instance methods pertain to an instance or object of a class and they can be referenced from anywhere inside the class definition. Public instance methods can be called on objects. + + +```ruby +class Person + def short_greet + 'Hey!' + end + + def long_greet + "#{short_greet} How you doin'?" + end +end + +Person.new.short_greet +Person.new.long_greet +``` + +In the code above, a `Person` class is defined with two methods: +- The `#short_greet` instance method which returns a string with value `'Hey!'`. +- The `#long_greet` instance method which references the `#short_greet` in its body and returns a string with the value `"#{short_greet} How you doin'?"`, where `#{short_greet}` will be replaced by the return value of the method `#short_greet`. diff --git a/RB129/test/study_guide.md b/RB129/test/study_guide.md index 2e24534..8c848a4 100644 --- a/RB129/test/study_guide.md +++ b/RB129/test/study_guide.md @@ -6,7 +6,7 @@ - [Use `attr_*` to create setter and getter methods](./getter_and_setter_methods.md) - [How to call setters and getters](./getter_and_setter_methods.md) - [Instance variables, class variables, and constants, including the scope of each type and how inheritance can affect that scope](./instance_class_and_constant_variables.md) -- Instance methods vs. class methods +- [Instance methods vs. class methods](./instance_methods_vs_class_methods.md) - Method Access Control - Referencing and setting instance variables vs. using getters and setters - Class inheritance, encapsulation, and polymorphism From 3f536af118b2c8fcf5893f7285a5c44ffcb75341 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Sat, 15 Oct 2022 14:28:40 +0200 Subject: [PATCH 15/17] fixup! [RB129] Instance methods vs. class methods --- .../test/instance_methods_vs_class_methods.md | 47 +++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/RB129/test/instance_methods_vs_class_methods.md b/RB129/test/instance_methods_vs_class_methods.md index 482cbc7..2e6209c 100644 --- a/RB129/test/instance_methods_vs_class_methods.md +++ b/RB129/test/instance_methods_vs_class_methods.md @@ -2,24 +2,55 @@ ## Instance methods -Instance methods are methods defined inside a class definition. Instance methods pertain to an instance or object of a class and they can be referenced from anywhere inside the class definition. Public instance methods can be called on objects. - +Instance methods are available to objects (or instances) of that class. Instance methods are defined inside the class body. They can be referenced from other instance methods and have access to both instance and class variables. ```ruby class Person + def initialize(name) + @name = name + end + def short_greet - 'Hey!' + 'Hello!' end def long_greet - "#{short_greet} How you doin'?" + "#{short_greet} My name is #{@name}. What is your name?" + end +end + +person = Person.new('John Doe') +person.short_greet # => "Hello!" +person.long_greet # => "Hello! My name is John Doe. What is your name?" +``` + +In the code above, a `Person` class is defined with three methods: +- The `#initialize` instance method which assigns the value assigned to the `name` parameter to the instance variable `@name`. +- The `#short_greet` instance method which returns a string with value `"Hello!"`. +- The `#long_greet` instance method which references the `#short_greet` instance method and the instance variabel `@name` in its body and returns a string with the value `"#{short_greet} My name is #{name}. What is your name?"`, where `#{short_greet}` will be replaced by the return value of the method `#short_greet` and `#{name}` will be replaced by the value assigned to instance variable `@name`. + +## Class methods + +Class methods are available to classes. Class methods are defined inside the class body by prepending the `self` keyword. They can be referenced from other class methods and have access to class variables. + +```ruby +class Person + @@number_of_persons = 0 + + def initialize + @@number_of_persons += 1 + end + + def self.number_of_persons + @@number_of_persons end end -Person.new.short_greet -Person.new.long_greet +Person.number_of_persons # => 0 +person = Person.new +Person.number_of_persons # => 1 ``` In the code above, a `Person` class is defined with two methods: -- The `#short_greet` instance method which returns a string with value `'Hey!'`. -- The `#long_greet` instance method which references the `#short_greet` in its body and returns a string with the value `"#{short_greet} How you doin'?"`, where `#{short_greet}` will be replaced by the return value of the method `#short_greet`. +- The `#initialize` instance method which increases the value assigned to the class variable `@@number_of_persons` by one. +- The `::number_of_persons` class method which returns the value assigned to the class variable `@@number_of_persons`. From 4e0c9c92fb804c8d7d035fc8711c69ae586e7415 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Sat, 15 Oct 2022 14:33:19 +0200 Subject: [PATCH 16/17] fixup! [RB129] Instance methods vs. class methods --- RB129/test/instance_methods_vs_class_methods.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/RB129/test/instance_methods_vs_class_methods.md b/RB129/test/instance_methods_vs_class_methods.md index 2e6209c..09a5763 100644 --- a/RB129/test/instance_methods_vs_class_methods.md +++ b/RB129/test/instance_methods_vs_class_methods.md @@ -44,13 +44,20 @@ class Person def self.number_of_persons @@number_of_persons end + + def self.next_number_of_persons + number_of_persons + 1 + end end -Person.number_of_persons # => 0 +Person.number_of_persons # => 0 +Person.next_number_of_persons # => 1 person = Person.new -Person.number_of_persons # => 1 +Person.number_of_persons # => 1 +Person.next_number_of_persons # => 2 ``` -In the code above, a `Person` class is defined with two methods: +In the code above, a `Person` class is defined with three methods: - The `#initialize` instance method which increases the value assigned to the class variable `@@number_of_persons` by one. - The `::number_of_persons` class method which returns the value assigned to the class variable `@@number_of_persons`. +- The `::next_number_of_persons` class method which references the class method `::number_of_persons` in its body and returns the return value of the class method `::number_of_persons` plus one. From e575afd42092e5ddbe9ca7dbce0b59805621b5f5 Mon Sep 17 00:00:00 2001 From: Aitor Lopez Beltran Date: Sat, 15 Oct 2022 15:17:00 +0200 Subject: [PATCH 17/17] [RB129] Method Access Control --- RB129/test/method_access_control.md | 109 ++++++++++++++++++++++++++++ RB129/test/study_guide.md | 2 +- 2 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 RB129/test/method_access_control.md diff --git a/RB129/test/method_access_control.md b/RB129/test/method_access_control.md new file mode 100644 index 0000000..31943e5 --- /dev/null +++ b/RB129/test/method_access_control.md @@ -0,0 +1,109 @@ +# Method Access Control + +Method Access Control is the concept of allowing or restricting the access to the methods defined in a class using access modifiers: `public`, `private`, and `protected` access modifiers. + +When prepending an access modifier method call to a method definition, the access modifier only applies to the method defined inmediately after. When the access modifier method call is used in its own line, the access modifier will apply to any method defined below it (unless access modifier method call is called after it to negate it). Note: methods defined without an access modifier are public methods by default. + +## Public methods + +Public methods are available to anyone who knows how to reference the owner of the methods. These methods comprise the class's interface (that's how other classes and objects will interact with this class and its objects). + +```ruby +class Dog + def bark + "Woof!" + end +end + +dog = Dog.new +dog.bark # => "Woof!" +``` + +```ruby +class Dog + public def bark + "Woof!" + end +end + +dog = Dog.new +dog.bark # => "Woof!" +``` + +```ruby +class Dog + public + + def bark + "Woof!" + end +end + +dog = Dog.new +dog.bark # => "Woof!" +``` + +## Private methods + +Private methods are only accessible from other methods in the class. + +```ruby +class Dog + def bark + random_bark + end + + private def random_bark + ["Woof!", "Bup!", "Guau!"].sample + end +end + +dog = Dog.new +dog.bark # => One of ["Woof!", "Bup!", "Guau!"] +``` + +```ruby +class Dog + def bark + random_bark + end + + private + + def random_bark + ["Woof!", "Bup!", "Guau!"].sample + end +end + +dog = Dog.new +dog.bark # => One of ["Woof!", "Bup!", "Guau!"] +``` + +## Protected methods + +Protected methods are similar to private methods in that they cannot be invoked outside the class. The main difference between them is that protected methods allow access between class instances, while private methods do not. + +```ruby +class Person + def initialize(age) + @age = age + end + + def older?(other_person) + age > other_person.age + end + + protected + + attr_reader :age +end + +person1 = Person.new(64) +person2 = Person.new(42) + +person1.older?(person2) # => true +person2.older?(person1) # => false + +person1.age + # => NoMethodError: protected method `age' called for # +``` diff --git a/RB129/test/study_guide.md b/RB129/test/study_guide.md index 8c848a4..a0ea669 100644 --- a/RB129/test/study_guide.md +++ b/RB129/test/study_guide.md @@ -7,7 +7,7 @@ - [How to call setters and getters](./getter_and_setter_methods.md) - [Instance variables, class variables, and constants, including the scope of each type and how inheritance can affect that scope](./instance_class_and_constant_variables.md) - [Instance methods vs. class methods](./instance_methods_vs_class_methods.md) -- Method Access Control +- [Method Access Control](./method_access_control.md) - Referencing and setting instance variables vs. using getters and setters - Class inheritance, encapsulation, and polymorphism - Modules