Let's take a break from our dogs. In this lesson, let's build a Cat class.
In C9, create a new file in your ruby_fundamentals
directory called cat.rb
. Open the file and create a new Cat
class:
class Cat
end
As we learned in previous lessons, for each class, we need an initialize
method:
class Cat
def initialize
end
end
For each cat, let's store the name
and the age
of the cat. That means that when we create a new Cat
object, we should be able to pass in the name and age as a parameter to the new
method (Cat.new(name, age)
).
Let's add the appropriate parameters to the initialize
method and store the values as instance variables:
class Cat
def initialize(name, age)
@name = name
@age = age
end
end
Now we can make a new instance of the Cat
class:
class Cat
def initialize(name, age)
@name = name
@age = age
end
end
cat = Cat.new("Cathy", 4)
What if we want to change the name
or the age
? Right now, there's no way to change the attributes for the cat. Let's create setter methods that will allow us to do this.
Setter methods are methods that allow you to set the values of instance variables for the object. On the other hand, getter methods are methods that return the value of an instance variable. As we'll see in this lesson, Ruby doesn't require that you create these methods for the most part, but in languages like Java, creating these setter and getter methods can be seen quite often.
class Cat
def initialize(name, age)
@name = name
@age = age
end
def name=(name)
@name = name
end
def age=(age)
@age = age
end
end
cat = Cat.new("Cathy", 4)
puts "Before: " + cat.inspect
cat.name = "Catherine"
cat.age = 5
puts "After: " + cat.inspect
The output will look like this:
As you can see, the name
and age
has changed.
Defining setter methods
If you are confused about the weird syntax of having
=
in a method name - don't worry it's not too complicated.When you execute
cat.name = "Catherine"
, you're actually executing a method that is namedname=
. That is why we created a method calledname=
:def name=(name) @name = name end
In other words,
name =
is just another method. We can rename the method to something random and it would still work:class Cat def initialize(name, age) @name = name @age = age end def coding_is_fun=(name) @name = name end def age=(age) @age = age end end cat = Cat.new("Cathy", 4) # This will work now cat.coding_is_fun = "Catherine" # This will give an error since the method name = isn't defined anymore cat.name = "Cath"
Next, what if we want to get the name
and the age
of a cat? What we need to do next is define a getter method. A getter method is a method that returns the value of a particular instance variable.
Defining a getter method is easy:
class Cat
def initialize(name, age)
@name = name
@age = age
end
def name=(name)
@name = name
end
def age=(age)
@age = age
end
def name
@name
end
def age
@age
end
end
cat = Cat.new("Cathy", 4)
puts "Before: " + cat.inspect
cat.name = "Catherine"
cat.age = 5
puts "After: " + cat.inspect
puts "Name: #{cat.name}"
puts "Age: #{cat.age}"
The output should look like this:
The methods we defined above return the instance variable when called.
We learned how we can create setter and getter methods for our classes. However, if we need to create these methods for every single attribute for each object, things can get repetitive and boring.
Fortunately in Ruby, we can define these setter and getter methods in a much more concise way. Introducing attr_reader
and attr_writer
.
attr_writer
replaces the setter methods:
class Cat
attr_writer :name, :age
def initialize(name, age)
@name = name
@age = age
end
# No need to define setter methods anymore!
# def name=(name)
# @name = name
# end
# def age=(age)
# @age = age
# end
def name
@name
end
def age
@age
end
end
attr_reader
replaces the getter methods:
class Cat
attr_writer :name, :age
attr_reader :name, :age
def initialize(name, age)
@name = name
@age = age
end
# No need to define setter methods anymore!
# def name=(name)
# @name = name
# end
# def age=(age)
# @age = age
# end
# No need to define getter methods anymore either!
# def name
# @name
# end
# def age
# @age
# end
end
Often times, we will use both attr_writer
and attr_reader
. To make things easier for us, Ruby also provides attr_accessor
, which is a combination of attr_writer
and attr_reader
:
class Cat
attr_accessor :name, :age
# attr_reader :name, :age
# attr_writer :name, :age
def initialize(name, age)
@name = name
@age = age
end
# No need to define setter methods anymore!
# def name=(name)
# @name = name
# end
# def age=(age)
# @age = age
# end
# No need to define getter methods anymore either!
# def name
# @name
# end
# def age
# @age
# end
end
The final code is this:
class Cat
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
end
Wow! Look how much less code we need to write! (Ruby is awesome.)
attr_writer
attr_reader
attr_accessor
combines attr_reader
and attr_writer
Car
class that you wrote in the last assignment