This presentation is available at:
https://presentations.generalassemb.ly/4c5ca2cc4e86d897d357#/1
-
Code a Ruby class
-
Instantiate a class to create objects
-
Code attributes (data) in a class
-
Write methods to set and access attributes
-
Write an
initialize
method to initialize an object at the time of instantiation -
Use
attr_reader
,attr_writer
&attr_accessor
to accomplish Ruby's mission of writing less code
-
In OOP, the programs we develop consist of objects that model the purpose of our application.
-
These objects interact with each other by invoking each other's methods, also known as sending messages.
-
By now, it's no big secret that everything in Ruby is an object.
-
Objects encapsulate:
- Attributes
and - Methods
- Attributes
-
Attributes are data held within an object.
-
They define the "properties" of an object. For example, if we had a house object, there might be attributes such as
square_footage
,num_bedrooms
, etc. -
Name a couple of attributes that a car object might have...
-
Methods define the behavior or actions available in an object.
-
They define what an object does. For example, that house object might have methods
set_alarm
,sell
,open_door
, etc. -
Name a couple of methods that a car object might have...
-
Model real-world objects that pertain to an application, for example, the user, the game board, the bank account, etc.
-
Interact with each other by calling each other's methods.
-
Contain attributes that describe the traits of the object.
-
Contain methods that implement the object's actions and behavior.
-
In Object Oriented Programming, the canonical analogy for describing a class is that it's a blueprint used to create objects.
-
Another good analogy is to think of a class as a factory that produces object instances of a certain class.
-
Let's define our first class!
Create a file namedbanana_stand.rb
and open it in your editor. -
Something fun & simple:
class BananaStand end
-
First question of the day: What's the naming convention used to name classes in Ruby?
-
There are no attributes or methods defined in there yet. No information, no behavior - we'll get to that later. However, although it doesn't contain anything yet, we can still create objects from it...
-
Let's see how we would create a new BananaStand object instance!
my_stand = BananaStand.new puts my_stand
-
As you can see, classes have a
new
method that's used to create an instance of a class. A process, not surprisingly, known as instantiation.
-
If you haven't done so already, run the program. The result look something like this:
#<BananaStand:0x007fabd98501b0>
-
What you see is the result of calling
to_s
on a custom object. It shows the object'sclass
and some crazy number that we don't need to worry about. -
Remember, you can always override this default behavior by defining a
to_s
method in your class to return a more useful representation of your object.
-
What's the difference between a Class and an Object?
-
An object's traits/properties are defined by its __________?
-
An object's behavior is defined by its __________?
-
Let's add some attributes to our silly
BananaStand
class - it's time to use those instance variables we talked about yesterday. -
What? You mean instance variables hold data in object instances of a class? Is that crazy or what? Not!
-
Remember, instance variables start with an
@
character:class BananaStand @color = "Yellow" @year_opened = 2003 @manager = "George Michael" end
-
Now that we've added some attributes, how do we access them?
-
It would be logical to believe that we could access them using dot notation like we did in JS or as in other languages like Java or C#.
-
You better sit down for this (never mind you're already seated)...
- What's a coder to do? Well, this isn't the first time you've heard the words getter and setter methods!
-
Let's write some methods to return the values of our attributes!
class BananaStand @color = "Yellow" @year_opened = 2003 @manager = "George Michael" def color @color end end
-
Now it's your turn, write the methods to return the
@year_opened
and@manager
attributes.
-
Now we can call those methods like any other method in Ruby:
puts my_stand.manager
-
Try it out.
What happened? I don't see s#%@!
-
It turns out that the code in a class outside of a method only runs once when the class is loaded. If the variables were class variables, not instance variables, they would remain in scope to all instances of the class - but this would result in all BananaStands having the same attribute values - boring and not very useful!
-
Allow me to demo for you changing the variables to have class scope.
-
Since each BananaStand object should be able to have its own attributes, we definitely need to use instance variables to hold the attribute values.
-
However, to successfully initialize instance variables, we need to initialize them within a special method named
initialize
. -
So, let's wrap our instance variables in an
initialize
like this:def initialize @color = "Yellow" @year_opened = 2003 @manager = "George Michael" end
-
Now try it!
-
Bravo, the
initialize
method is automatically called for us! -
What method does
initialize
mimic in JavaScript?
-
George Michael has been a terrible manager, so how can we change the value of the
@manager
variable? -
Let's see what setter methods look like - they look a little funky at first, but you'll get used to them:
def manager=(new_manager) @manager = new_manager end
-
So, when we write
manager = "Anyone but George"
, you're telling me that we're actually calling that object'smanager=
method and passing in the new manager name as an argument? Yup, that's what's going on all righty!
-
Time to fire George:
my_stand = BananaStand.new my_stand.manager = "Pee-wee Herman" puts my_stand.manager
Excellent!
-
Now it's your turn:
- Write the setter methods for the
color
andyear_opened
attributes - You have 3 minutes...
- Write the setter methods for the
Congrats, you've now written a BananaStand class with attributes and accessor methods that get and set the values of those attributes.
- What's the special method in a class that is automatically called by Ruby when we create an instance of it?
-
Obviously it would be nice to be able to set the values of our object's attributes at the time we instantiate the object instead of having to set each attribute separately after we create it.
-
Since
initialize
is just a method, we can write it to accept arguments!def initialize(color, year_opened, manager) @color = color @year_opened = year_opened @manager = manager end
-
Now we can create all the custom
BananaStands
we want!my_stand = BananaStand.new "Pink", 1985, "Pee-wee Herman"
-
Coding all those getters and setters for every attribute gets tedious in a hurry.
-
Not surprisingly, Ruby has methods for just about anything you can think of.
-
To provide read and write access to attributes we can use the
attr_reader
andattr_writer
methods respectively:# Replaces all getter methods attr_reader :color, :year_opened, :manager # Replaces all setter methods attr_writer :color, :year_opened, :manager
Note how we can use symbols to save memory when specifying the attribute names.
-
Providing both read and write access to an object's attributes is so popular, Ruby provides us with a one-stop solution:
class BananaStand attr_accessor :color, :year_opened, :manager def initialize(color, year_opened, manager) @color = color @year_opened = year_opened @manager = manager end end
-
That's what were talking about!
-
Define a class called
Game
. -
Give the
Game
class two attributes,player1
andplayer2
. Allow two player's names to be passed in at time of instantiation. -
Provide
attr_accessor
methods for theplayer1
andplayer2
attributes.
Take 2 minutes to review these questions before we review them in class:
-
Unlike in JavaScript, we cannot read or change the values of an object's attributes directly. Instead, we must write ________ and/or ________ methods or use Ruby's ________ methods.
-
What's instantiation?
-
What sort of variable do we use inside an object to share information throughout that object, including inside all of its methods?