Question | Click to View Answer |
What does the following code print? Explain. module M
def hi
'hey hey'
end
end
class A
include M
end
p A.instance_methods.include? :hi
|
true
Methods defined in a module are accessible as instance methods when the module is included in a class. |
What does the following code print? Explain. module Stuff
def self.hi
'hey there partner'
end
end
class Lamp
include Stuff
end
p Lamp.hi
|
This code raises the following exception: "NoMethodError: undefined method `hi' for Lamp:Class." The :hi method lives in the singleton class of the Stuff module and is ignored when Stuff is included in the Lamp class. |
What does the following code print? Explain. module AAA
def hi; 'AAA#hi'; end
end
class Money
class << self
include AAA
end
end
p Money.hi
|
"AAA#hi"
The 'class << self' syntax is used to change the scope to Money's singleton class. The module's methods are added to the singleton class as instance methods when the module is included in the singleton class. Money.singleton_methods # => [:hi] |
What does the following code print? Explain. module AAA
def hi; 'AAA#hi'; end
end
class Money
extend AAA
end
p Money.hi
|
extend is another way to add methods to the singleton class of a class. As in the previous example, the :hi method is accessible as a singleton method of Money: Money.singleton_methods # => [:hi]
|
What does the following code print? Explain. module Ghost
def self.boo; end
class << self
def hi; end
end
def bye; end
end
p Ghost.singleton_methods
|
[:boo, :hi]
The :boo and :hi methods are bound to Ghost's singleton class. As with classes, there are many ways to create singleton methods for modules. |
Add code to the Bob module so both of the following print statements can run without raising and exception. module Bob
def job
"gettin' loaded"
end
end
class A; include Bob; end
p Bob.job
p A.new.job
|
module Bob
def job
"gettin' loaded"
end
module_function :job
end
The module_function method creates singleton methods for the module object. |
What does the following code print? Explain. module Simpsons
def homer; end
module_function :homer
instance_eval do
def bart; end
end
end
p Simpsons.singleton_methods
|
[:homer, :bart]
instance_eval evaluates a block of code in the context of an object (the implicit self in this example) so it can be used to add singleton methods. |
What does the following code print? Explain. module Window
def hi; 'Window#hi'; end
end
module Shade
def hi; 'Shade#hi'; end
end
class BBB
include Window
include Shade
end
p BBB.new.hi
|
"Shade#hi"
Modules are added immediately to the right of the including class (BBB) when they're included. Window is added to the right of BBB in the method lookup chain and then Shade is added to the right of BBB in the method lookup chain. Therefore, Ruby looks for methods in the Shade module before looking for methods in the Window module. |
What does the following code print? Explain. module X; end
module Y; end
class Z
include Y
include X
end
p Z.ancestors
|
[Z, X, Y, Object, Kernel, BasicObject]
When Y is included, it is added immediately to the right of Z in the ancestors chain. When X is included, it is added immediately to the right of Z in the ancestors chain, thus moving Y one position to the right. |
What does the following code print? Explain. module Cat; end
module M; end
class Feline
extend Cat
class << self
include M
end
end
p Feline.singleton_class.ancestors
|
[#<Class:Feline>, M, Cat, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject]
M and Cat are added to the method lookup chain of the singleton class in a similar manner. |
Update the code to bypass the module scope gate. x = 'i am variable'
module M
def silly
x
end
module_function :silly
end
p M.silly
|
x = 'i am variable'
M = Module.new do
define_method(:silly) do
x
end
module_function :silly
end
|
What does the following code print. module Batman
def self.sidekick
'robin'
end
end
p Batman::sidekick
|
'robin'
Singleton methods of a module can either be called with dot notation (Batman.sidekick) or :: notation (Batman::sidekick). |
Explain what the following code prints and how it works. module M
def self.included(obj)
obj.extend(SingletonMethods)
end
def yo; 'yo yo'; end
module SingletonMethods
def hi; 'hey hey'; end
end
end
class C
include M
end
p C.new.yo
p C.hi
|
'yo yo'
'hey hey'
This is a common Ruby design pattern to include instance methods and singleton methods to a class from a single module. The M.included? callback method is run when M is included in C and enables the singleton methods to be included in the singleton class. This is a nifty design pattern that's used by many Ruby libraries and should be memorized. |