Lesson 8 of 11
Modules & Mixins
Learn how group related and share them between classes. `include` adds a module's methods as methods and `extend` adds them as class methods; this is called a mixin.
# Modules serve two purposes:
# 1. Namespacing (organizing code)
# 2. Mixins (sharing behavior across classes)
module Greetable
def greet
"Hello! I'm #{name}." # assumes the including class has a name method
end
def farewell
"Goodbye from #{name}!"
end
end
module Serializable
def to_json_str
vars = instance_variables.map do |var|
""#{var.to_s[1..]}": "#{instance_variable_get(var)}""
end
"{ #{vars.join(", ")} }"
end
end
class Person
include Greetable
include Serializable
attr_reader :name, :age
def initialize(name, age)
@name = name
@age = age
end
end
alice = Person.new("Alice", 30)
puts alice.greet # Hello! I'm Alice.
puts alice.farewell # Goodbye from Alice!
puts alice.to_json_str # { "name": "Alice", "age": "30" }# Comparable — include it and define <=> to get all comparison operators free
class Temperature
include Comparable
attr_reader :degrees
def initialize(degrees)
@degrees = degrees.to_f
end
# <=> is the "spaceship operator" — required by Comparable
def <=>(other)
degrees <=> other.degrees
end
def to_s
"#{degrees}°"
end
end
temps = [Temperature.new(100), Temperature.new(0), Temperature.new(37)]
puts temps.min # 0.0°
puts temps.max # 100.0°
puts temps.sort.inspect
puts Temperature.new(37) > Temperature.new(20) # true
puts Temperature.new(37).between?(Temperature.new(36), Temperature.new(38)) # true
# Enumerable — include it and define each() to get map/select/reduce/etc.
class NumberSet
include Enumerable
def initialize(*nums)
@data = nums
end
def each(&block)
@data.each(&block)
end
end
ns = NumberSet.new(3, 1, 4, 1, 5, 9)
puts ns.sort.inspect # [1, 1, 3, 4, 5, 9]
puts ns.select(&:odd?).inspect # [3, 1, 1, 5, 9]
puts ns.min # 1Finished reading?Mark it done to track your progress.
Tip: use the ← and → keys to move between lessons.