This section introduces Ruby's object-oriented programming model, including instances, methods, parameters, and memory management (instances and references). Later sections cover classes and modules and further topics.
Ref: WGR Chapter 2. Objects, methods, and local variables
Note: Following WGR's lead, in this section we define methods on instances (not on classes), to keep the lessons simple.
An object encapsulates state and behavior.
One way to think about objects:
Objects are things that can be described and can do things, or...
cookie = Object.new
cookie
refers to an object instance
fruit = "apple"
"apple"
is a string literal
fruit
now refers to a new object instance
Stack | Heap | |
---|---|---|
fruit | -> | "apple" |
fruit = "apple"
dessert = "apple"
fruit
refers to a new object instance
dessert
refers to a different, new object instanceStack | Heap | |
---|---|---|
fruit | -> | "apple" |
dessert | -> | "apple" |
fruit = "apple"
dessert = fruit
fruit = "banana"
dessert = fruit
What are the values of fruit
and dessert
after each line?
How can you tell if two references point to the same instance?
fruit = "apple"
dessert = "apple"
>> fruit.object_id
=> 2165091560
>> dessert.object_id
=> 2165084200
Ref. WGR Ch.2, Section 2.3.1
==
params are equal (overridable).eql?
params are equal and the same type.equal?
params are identical (same object_id
)==
is usually what you wantNote that .equal?
is not guaranteed since bizarrely, some objects override .equal?
to do something else. If you really want to know if two variables reference the same instance, compare their object_id
s.
fruit = "apple"
fruit = "banana"
friend = "Alice"
teacher = friend
friend.upcase!
teacher
=> "ALICE"
cookie = Object.new
def cookie.bake
puts "the oven is nice and warm"
end
def cookie.
("def cookie dot") means "define a method on cookie"Behavior comes from messages and methods.
cookie.bake
prints I'm a cookie
to the console
cookie
receives the message bake
and executes the method bake
.
) is the message operator
Ref. The Well-Grounded Rubyist PDF, Fig. 2.1
methods
method>> cookie.methods
=> [:nil?, :===, :=~, :!~, :eql?, ...]
>> cookie.methods(false)
=> [:bake]
also useful: cookie.methods.sort
, cookie.methods.grep(/age/)
>> cookie = Object.new
=> #<Object:0x007f86e485c3a8>
>> cookie.methods(false)
=> []
>> def cookie.bake; puts "hi"; end
=> nil
>> cookie.methods(false)
=> [:bake]
>> "goo".methods.grep(/sub/)
=> [:sub, :gsub, :sub!, :gsub!]
respond_to?
methodif cookie.respond_to? :bake
cookie.bake
else
puts "cookie is unbakable"
end
Note: Usually you don't use respond_to
because of duck typing.
def cookie.add_chips(num_chips)
@chips = num_chips
end
def cookie.yummy?
@chips > 100
end
cookie.add_chips(500)
cookie.yummy? #=> true
self
is the default message receiver
self
is set invisibly to always point to the current object
def cookie.yummy?
@chips > 100
end
def cookie.add_chips(num_chips = 10)
@chips
@chips += num_chips
end
def cookie.yummify
add_chips until yummy?
end
yummify
the call to yummy?
goes to self
/