Question | Click to View Answer |
What does the following code print? Explain how the @bark instance variable is used in the speak() method. class Dog
def initialize
@bark = "ruff ruff"
end
def speak
"I like to #{@bark}"
end
end
fido = Dog.new
puts fido.speak()
|
The @bark instance variable is set to the value "ruff ruff" in the initialize() method. Instance variables can be accessed by any instance methods in a class and are used to maintain "state" (state is the data that objects "know"). |
What does the following code print? Explain the result. class Computer
def initialize
@sound = "beep beep"
end
def self.about
"Sometimes I go #{@sound}"
end
end
p Computer.about
|
"Sometimes I go "
The about() method is a class method and does not have access to the @sound instance variable. @sound is only available to the instance methods, not the class methods. Undefined instance variables have a default value of nil. |
What does the following code print? class Xyz
def pots
@nice
end
end
xyz = Xyz.new
p xyz.pots
|
nil
The @nice instance variable has not been assigned to anything, so its value is nil by default. |
What does the following code print? class Xyz
def paper
unassigned_local_variable
end
end
xyz = Xyz.new
p xyz.paper
|
This raises an exception and provides the following message: undefined local variable or method `unassigned_local_variable'. The Ruby interpreter does not know if unassigned_local_variable is an unassigned local variable or an undefined method. An exception is raised because local variables must be assigned to a value (unlike instance variables that default to a value of nil). |
What does the following code print? Explain what happens when the meaning_of_life() method is run multiple times for a given object. class Something
def meaning_of_life
@result ||= result
"The meaning of life is the number #{@result}"
end
def result
Math.log10(100) * 42 - 48 - 13
end
end
something = Something.new
p something.meaning_of_life
|
The meaning of life is the number 23
When the meaning_of_life() method is run, the return value of the result() method is assigned to the @result instance variable, but only when @result is nil. When the meaning_of_life() method is initially run, @result is nil, so the code in the result() method is executed. When the meaning_of_life() is run again, @result is not nil, so the result() method is not executed. The ||= operator (pronounced "or-equal operator") is useful for caching values in instance variables and preventing code from needlessly running when values have already been calculated. |
What does the following code print? Explain. class Cup
PURPOSE = "hold liquids"
def main_use
PURPOSE
end
end
tea_cup = Cup.new
p tea_cup.main_use
|
"hold liquids"
PURPOSE is a constant that is assigned to the value "hold liquids". Constants are accessible by instance methods. |
What does the following code print? Explain. class Chair
AGE = "been around the block"
def self.about
"I'm old and I've #{AGE}"
end
end
p Chair.about
|
"I'm old and I've been around the block"
The AGE constant is assigned to the value "been around the block". The AGE constant is accessible by the about class method. |
What does the following code print? Explain. BEST_MOVIE = "Clueless"
BEST_MOVIE = "Mean Girls"
p BEST_MOVIE
|
"Mean Girls"
BEST_MOVIE is a constant and can be reassigned to another value just like other variables. Constants are not constant if they are being reassigned, so reassigning constants is not advisable. Ruby will give you a warning when you reassign a constant, but does not raise an exception and allows the reassignment to take place. |
What does the following code print? Explain. class Bottle
DRANK = "lemme hit that"
end
p Bottle::DRANK
|
"lemme hit that"
The Bottle::DRANK allows the constant to be accessed outside of the class. This namespacing of constants is useful, so there is not a namespace collision if there is another DRANK constant in a different class. |
Explain the following statement: "Everything in Ruby is an object, so there are no standalone functions in Ruby, all functions are really methods". |
Methods are functions that are associated with a specific object. Everything is an object in Ruby, including all instances of classes and classes themselves, so there cannot be any standalone functions, and all functions are methods. |
Explain how the Pig#main_desire method can call the weight() method without using the keyword self. class Pig
def weight()
"500 pounds"
end
def main_desire()
"eat all day and be more than #{weight()}"
end
end
piggy = Pig.new()
piggy.main_desire()
|
When piggy.main_desire() is called, the piggy object must locate the value of the weight() method to respond. When an explicit self is not used (i.e. self.weight()), Ruby falls back to the implicit self value. The implicit self equals the object itself in instance methods. In this example, the implicit self refers to the piggy object. |
Explain the Fan.about method and why the about() method definition uses the keyword self. class Fan
def self.about
"my job is to keep people cool"
end
end
p Fan.about
|
The Fan.about method is a class method, meaning that the about method is defined directly on the Fan class object. Notice that the about message needs to be sent to the Fan object itself, not instances of the Fan class. The default value for self is the class itself for code that is in the class definition, but not in an instance method. |
What does the following code print? class Woman
SELF = self
end
p Woman::SELF
|
Woman
SELF is a constant value and self is a special reserved keyword in Ruby. In this example, the SELF constant is assigned to the value of the special reserved keyword. When self is in the class definition, but not in an instance method, it refers to the class itself, or Woman in this case. |
What does the following code print? Explain. class Dude
end
def Dude.motto
"Cowabunga"
end
p Dude.motto
|
"Cowabunga"
The Dude class is initially defined without any instance or class methods. The Dude.motto method is then defined as a singleton method on the Dude object. Singleton methods are methods that are defined for a particular object (as opposed to instance methods that are defined for all objects made by the class). Class methods in Ruby are really just singleton methods defined for the class object. |
What does the following code print? Explain. class Phone
def Phone.job
"Distract you from life"
end
end
p Phone.job
|
"Distract you from life"
The Phone.job class method is a singleton method on the phone class. Both the self keyword and the Phone class object name can be used to define class methods. Here is another way to write the code with the same behavior. class Phone
def self.job
"Distract you from life"
end
end
|
What does the following code print? def blah
"blah blah"
end
class Dog
def speak
"I am #{blah}"
end
end
p Dog.new.speak
|
"I am blah blah"
The blah() method is a method of the Object class. It is tempting to think the blah() method is not associated with any class, but all methods in Ruby are bound to some class, even if the class definition is not visible. The Dog class inherits from the Object class and has access to the blah() method. |
Identify the object, message, method, and receiver in the following example. x = 5.to_f
|
5 is the object (instance of the Fixnum class) to_f is the message that is sent to the object 5 The method to_f is called on the object 5 The object 5 is the receiver of the message |
Use the following code to describe how the message is sent, the receiver of the message, and the content of the message. "table".upcase()
|
This example uses "dot notation" to send the upcase message to the "table" object. The "table" object is the receiver of the "upcase" message and invokes the upcase() method when it receives the "upcase" message. |
Describe the message and receiver in the following example. class Calculator
def add(x, y)
x + y
end
end
my_calculator = Calculator.new
my_calculator.send(:add, 3, 4)
|
my_calculator is the calculator object that is the receiver of the "add" message (and the two arguments that are sent with the add message). When the my_calculator object receives the "add" message, it invokes the add() method. Dot notation is a more common way to send messages (i..e my_calculator.add(3, 4)), but the send() method can also be used to send messages. |
Describe the message receiver and message in the following example. 3 + 4
|
3 is the receiver of the "+" message. When 3 receives the "+" message, it invokes the +() method with the argument 4. 3 + 4 uses syntactic sugar to make the code more readable, but the expression can also use dot notation or the send() method. 3.+(4) # dot notation
3.send(:+, 4) # send() method
|
Describe the message sender, message receiver, and message when the Circle#area method is called in the following example. class Circle
def area(radius)
calc = Calculator.new
calc.pi * radius ** 2
end
end
class Calculator
def pi
3.14
end
end
my_circle = Circle.new
p my_circle.area(3)
|
When the Circle#area method is called the my_circle object (message sender) sends the "new" message to the Calculator class to instantiate a calc object. Then the my_circle object sends the "pi" message to the calc object (message receiver) to compute the area. The message sender sends messages and the message receiver is responsible for finding a method corresponding to the message in the inheritance chain, invoking the method, and responding with a value. |