Modules & Classes
Classes
Class is a built-in Ruby object which inherits from the Module class, another built-in Ruby object.
The Ruby Class object can be used to create Ruby classes that is objects with the ability of instantiation.
class Animal
end
Animal.class # => Class
Instances
To initialize
an instance of a given class the static method :new
is called. The arguments (zero or more) and behaviour of :new
method is defined using initialize
method.
class Animal
def initialize(species:, name:)
@species = species
@name = name
end
end
Animal.new(species: 'fish', name: 'Wanda').class # => Animal
Methods & Self
Methods defined within a class are instance methods not the class object's (aka static
) methods unless they are defined on the class object itself using def self.foo
(or def Bar.foo
) or an idiom class << self
is used.
class Thing
def inspect_instance_self
puts self
end
def self.inspect_class_self # == def Thing.inspect_class_self
puts self
end
end
Thing.inspect_instance_self # NoMethodError (undefined method `inspect_self' for Thing:Class)
Thing.inspect_class_self # => Thing
Thing.new.inspect_instance_self # => #<Thing:0x00007fa25187e808>
Thing.new.inspect_class_self # => NoMethodError (undefined method `inspect_class_self' for #<Thing:0x00007fa25500d418>)
When the idiom class << self
is used the methods defined within its block are the class static methods.
class Item
class << self
def inspect_self
puts self
end
end
end
Item.inspect_self # Item
Item.new.inspect_self # NoMethodError (undefined method `inspect_self' for #<Item:0x00007fcf8c0845e0>)
Each Object Has Two Classes
It is sometimes inaccurately said that in Ruby a given object has only one class. In Ruby each object has exactly one named class - its direct ancestor - and the second one - existing beside the direct ancestor class - called a singleton
or an eigenclass
class. Methods defined with self.foo
or << self
are defined as methods of the eigenclass and used as singleton methods.
Inheritance
Each class in Ruby inherits from some other class - its direct ancestor. Methods and constants defined within a given class ancestor and ancestors of its ancestor are available within the class.
class Airplane
def self.inspect
'Inspecting'
end
def fly
'Flying'
end
end
class Jet < Airplane
end
Jet.inspect # "Inspecting"
Jet.new.fly # "Flying"
Instance Variables
Instance variables are denoted with @
and assigned to a specific instance of a Ruby class.
class Animal
def initialize(species:, name:)
@species = species
@name = name
end
end
an_animal = Animal.new(species: 'horse', name: 'Roach') # => <Animal:0x00007fd4801896e0 @name="Roach", @species="horse">
If a get
method is defined within the class of the instance then it is possible to get a specific instance variable through sending a message with the name of the get method to the instance.
If a set
method is defined within the class of the instance it is possible to set a specific instance variable through sending a message with the name of the set method to the instance (syntactic sugar for =
can be used).
class Animal
def initialize(species:, name:)
@species = species
@name = name
end
# get method
def name
@name
end
# set method
def name=(name)
@name = name
end
end
an_animal = Animal.new(species: 'horse', name: 'Roach') # => <Animal:0x00007fd4801896e0 @name="Roach", @species="horse">
an_animal.name # => "Roach"
an_animal.name = "Kelpie"
an_animal.name # => "Kelpie"
attr_reader :name
can be used instead of def name
, attr_writer :name
can be used instead of def name=(name)
. attr_accessor
combines attr_reader
and attr_writer
.
Modules
The Module class is a built-in Ruby object instances of which 1) provide namespaces allowing for collision-free defining of constants and methods, 2) enable broadening of classes' functionalities through mixins.
Creation of a module is signalled by the module
reserved word.
module CustomMath
def sum(a, b)
a + b
end
end
Including Modules
When a class includes a module with an include
keyword the non-static methods defined in the module become the class'es instance methods.
class SimpleMath
include CustomMath
end
simple_math = SimpleMath.new # => <SimpleMath:0x00007fd630054700>
simple_math.sum(2, 2) # => 4
Prepending Modules
prepend
works similarly to include
and the difference between the two is that prepend
gives precedence to methods defined in the module to those defined directly in the class.
Extending Classes with Modules
Extending a class with a module with an extend
keyword makes the non-static methods defined in the module to be available within the class as the class methods.