What is the DRY rule?
Don’t Repeat Yourself and avoid repeating code
How do you create a class? What is the benefit of creating a class?
Class allows you to apply the DRY rule to avoid having to repeat bits of information over and over again.
To create a class we use the < “class” > keyword, and the name of a class must begin with a capital letter.
for example…
class Cat
def initialize(name, color, age)
@name = name
@color = color
@age = age
end
endThe @ symbol denotes an instance variable or attribute of our class
So for the example above, the Cat class will have attributes of @name, @color, @age
After initializing a class, how do we execute upon it and create instances or objects associated with the class?
Once you’ve initialized your class, you can create a new object under that class by using < class name >.new( attributes ).
The class name should be the singular of whatever object is being defined like “Cat” instead of “Cats.”
class Cat
def initialize(name, color, age)
@name = name
@color = color
@age = age
end
endcat_1 = Cat.new("Sennacy", "brown", 3)
cat_2 = Cat.new("Whiskers", "white", 5)What is a Getter Method?
Way to get or return an attribute of an object belonging to a class. So in this example for Cat, we created the “get_name” method which calls on the “@name” attribute.
To execute on the getter method, we need to call on the cat INSTANCE (i.e. cat_1) instead of the class. It’s called, using this format “ < instance name >. “ -> cat_1.get_name
Without the getter method, there’s no way to refer or grab that attribute. A getter method can only return the value of an attribute. It cannot be used to modify the attribute like changing the cat’s age.
class Cat
def initialize(name, color, age)
@name = name
@color = color
@age = age
enddef name
@name
end
end
def color
@color
end
end
cat_1 = Cat.new(“Sennacy”, “brown”, 3)
p cat_1.name # “Sennacy”
p cat_1.color #”brown”
What is a Setter Method?
IMPORTANT: You need to set the Getter method FIRST before you can create the Setter Method. The Setter Method will not work without the Getter method created first.
Allows you to change the value of an attribute after it’s already been “set”.
For the cat_1 example below, the age was originally 3, but say we want to change to 42. We can do that by creating a “setter” method where we add “age = number”
class Cat
def initialize(name, color, age)
@name = name
@color = color
@age = age
enddef age = (number)
@age = number
end
end
cat_1 = Cat.new("Sennacy", "brown", 3)
cat_1.age = 42 #this will change the value of the age from 3 to 42What are ways to implement other types of methods within a class?
class Cat
def initialize(name, color, age)
@name = name
@color = color
@age = age
end
def purr
if @age > 5
puts @name.upcase + " goes purrrrrr..."
else
puts "..."
end
end
endcat_1 = Cat.new(“Sennacy”, “brown”, 10)
cat_1.purr # “SENNACY goes purrrrrr…”
cat_2 = Cat.new(“Whiskers”, “white”, 3)
cat_2.purr # “…”
What is a Class Variable?
An instance variable are denoted by @ and typically assigned insider the #initialize when creating a class. The instance variable is shared attribute across all objects of that class but the attribute itself can change from object to object. Like cars having different colors.
The CLASS VARIABLE sits outside of the #initialize (but still within the Class definition) and is denoted by @@. The @@ClassVariable is a single shared variable across all objects. E.g. the class variable -> @@num_wheels will be 4 and all cars under the Car class will have 4 wheels.
Class variables can be changed but once it changes, it’ll affect every instance created once it changes and will create in the future.
What is a Class Constant?
For safety, you can create a class constant which cannot be reassigned. A class constant name must be capitalized.
What are the three different ways to create a variable within a class?
What is an Instance Method?
An instance method is a method that calls on an instance of a class.
In the example below, “#speak” is an instance method as it calls on the Dog instance we initialized using Dog.new.
If something is an instance of a class, it shares the same instance attributes (@) and can be created with < class name >.new
class Dog
def initialize(name, bark)
@name = name
@bark = bark
enddef speak
@name + “ says “ + @bark
end
end
my_dog = Dog.new(“Fido”, “woof”)
my_dog.speak # “Fido says woof”
What is a Class Method? What is the symbol associated with it?
A Class Method is a method that calls directly on the class by adding “self.” before the method name. Here’s the example “self.growl”. A Class method applies to all objects within the class.
ASSOCIATED WITH DOUBLE COLONS “::”
For notation we’ll use Dog::growl to denote that growl is a class method of Dog.
We then call on the method by using . = i.e. Dog.growl
Class#method_name means method_name is an instance method (e.g. my_dog.speak -> will only work with my_dog the object)
Class::method_name means method_name is a class method (e.g. Dog.growl -> applies to the whole class)
class Dog
def initialize(name, bark)
@name = name
@bark = bark
end def self.whos_louder(dog_1, dog_2)
if dog_1.bark.length > dog_2.bark.length
return dog_1.name
elsif dog_1.bark.length < dog_2.bark.length
return dog_2.name
else
return nil
end
enddef name
@name
end
def bark
@bark
end
end
d1 = Dog.new(“Fido”, “woof”)
d2 = Dog.new(“Doge”, “much bork”)
p Dog.whos_louder(d1, d2) # “Doge”
How do you “monkey patch” or add methods within a class like class Array?
Create the method like normal but use “self” to refer to the Array or whatever class is being used.
What is Separation of Concerns?
A design principle that focuses on implement one class in a single file for greater organization and clarity.
See example below. Anything without the .rb ending is a folder like “project root” and
“other_animals”
project_root
├── pet_hotel.rb
├── cat.rb
└── other_animals
└── dog.rbWhat is Require Relative?
“require_relative” is a method used to specify a path to another ruby file.
For example…see below. To run our hotel, we would just need to execute ruby pet_hotel.rb. Because pet_hotel.rb AS THE MASTER FILE requires cat.rb and dog.rb, the code in those files will also execute.
project_root/pet_hotel.rb
# Let's require the last two files, by specifying their path's relative to this pet_hotel.rb file require_relative "./cat.rb" require_relative "./other_animals/dog.rb"
class PetHotel
def initialize(name)
@name = name
@guests = []
endWhat is the difference between running just “require” and “require_relative”?
We use the plain require because we run the code using RSPEC via bundle exec rspec. RSPEC will automatically run the code in a certain configuration where it will automatically know to look inside of the /lib folder. In fact, RSPEC is designed to be used where you have a separate /spec and /lib folders. To get into the nitty gritty details, RSPEC will configure the $LOAD_PATH for us.
As a rule of thumb, we’ll use the plain require where gems are involved. In the previous sections that used the byebug gem, we had to write require “byebug” to access the debugger. It’s obvious that we don’t have an explicit byebug.rb file in those old projects. This is because ruby already knows where to find byebug through the $LOAD_PATH.
What is the built-in method for user input?
“gets” - built-in method will halt execution of the code and allows the user to type characters until they hit enter.
p “Enter your name:”
name = gets
p “hello “ + name
What’s a nuisance of getting user input? How do we deal with it?
When user hits the “enter” button, it’ll translate to adding “\n” a newline code to the end of the user-typed response.
Need to add .chomp at the end to remove the newline or carriage return characters.
puts “Enter ‘yes’ or ‘no’”
response = gets.chomp
if response == "yes" puts "yup!" elsif response == "no" puts "nah!" else puts "I'm sorry, my responses are limited." end
What happens with a user inputs a number? How do we deal with it?
A common error is when a user inputs an integer and it automatically comes back as a string.
Need to convert to an integer using “.to_i”
puts “Enter a number: “
num = gets.chomp.to_i
puts 2 * num
What are the two pillars of Object Oriented Programming (OOP)?
Another example, Array is a class and Array#include? is a method that we feel comfortable using although we do not know the exact implementation details within the method
Encapsulation can be achieved by declaring all the variables in the class as private and writing public methods in the class to set and get the values of variables.
For example, if there was a Queue class and within the class methods to define adding and removing people from the line. To avoid havoc, the queue class will avoid any getter or setter methods to be able to enforce the rules and keep it secure.
What is a method to create getters automatically to avoid repetition?
“attr_reader” is a built-in method that is called inside a Class (but not within “initialize”).
They’re passed in as symbols that correspond to the attributes that need getters.
By convention, we omit parentheses for attr methods but they can take multiple attributes at a time.
Examples:
attr_reader(:name, :age) is the same as attr_reader :name, :age
class MyClass
attr_reader :attribute_1
# …
end
What is a built in method to automatically create setter methods?
“attr_writer”
attr_writer :name, :age is the equivalent of explicitly writing out a setter method like below:
def name=(new_name)
@name = (new_name)
end
def age=(new_age)
@age = (new_age)
end
What is a built in method that allows you to create both a getter and setter method?
“attr_accessor” simultaneously gets and sets the attributes. Should be used sparingly given that data may need to be encapsulated or shielded from misuse.
attr_accessor :name, :age
What is Syntactic Sugar?
these are “shortcuts” to make the code more readable and elegant.
def ==(other_person)
self.last_name == other_person.last_name
end
For example, instead of this
person_1.==(person_2)
do this instead…
person_1 == person_2
How can you create a random number?
rand(min..max)