In Ruby, both include
and extend
are used to incorporate modules into classes, but they serve different purposes and are used in different contexts. Understanding the difference between these two methods is crucial for effectively organizing and utilizing code in Ruby applications.
Here’s a detailed explanation of the differences between include
and extend
:
include
- Purpose:
include
is used to add the module’s instance methods to the target class. - Usage: When you include a module in a class, the module’s methods become instance methods of the class.
- Scope: Affects instances of the class. Any object created from the class will have access to the module’s methods.
- Inheritance: If a subclass is created from the parent class that included the module, the subclass will also have access to the module’s methods.
Example
1
2
3
4
5
6
7
8
9
10
11
12
module Greetings
def hello
"Hello!"
end
end
class Person
include Greetings
end
person = Person.new
puts person.hello # Output: "Hello!"
In this example, the hello
method from the Greetings
module is available as an instance method of the Person
class. Any instance of Person
can call hello
.
extend
- Purpose:
extend
is used to add the module’s methods as class methods to the target object. - Usage: When you extend a module in a class (or on an object), the module’s methods become class methods.
- Scope: Affects the class itself or the object it’s called on. The methods become part of the object’s singleton class.
- Inheritance: Extending a module does not make the module’s methods available to instances of the class, only to the class itself or to the extended object.
Example
1
2
3
4
5
6
7
8
9
10
11
module Greetings
def hello
"Hello!"
end
end
class Person
extend Greetings
end
puts Person.hello # Output: "Hello!"
In this example, the hello
method from the Greetings
module is available as a class method of the Person
class. The Person
class itself can call hello
, but instances of Person
cannot.
Key Differences
Feature | include |
extend |
---|---|---|
Scope | Instance-level: adds instance methods | Class-level: adds class methods |
Usage | Mixes in methods to be available for instances | Adds methods to the class or object itself |
Inheritance | Methods are available to subclass instances | Methods are not inherited by subclass instances |
Purpose | Share behaviors across instances of multiple classes | Enhance the class or object with additional methods |
When to Use include
vs. extend
-
Use
include
when you want to share common behaviors among instances of different classes. It’s ideal for adding functionality to instances.1 2 3 4 5 6 7 8 9 10 11 12
module Loggable def log(message) puts "[LOG] #{message}" end end class User include Loggable end user = User.new user.log("This is a log message.") # Output: "[LOG] This is a log message."
-
Use
extend
when you want to enhance a class or a specific object with additional methods, typically for utility or class-level functionality.1 2 3 4 5 6 7 8 9 10 11
module ClassLogger def log_class_activity puts "Class activity logged." end end class User extend ClassLogger end User.log_class_activity # Output: "Class activity logged."
Combining include
and extend
Sometimes, you might want to use both include
and extend
to provide both instance and class methods. You can do this by defining the instance methods directly in the module and using a nested module for class methods:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module Greetings
def hello
"Hello from instance!"
end
module ClassMethods
def hello
"Hello from class!"
end
end
def self.included(base)
base.extend(ClassMethods)
end
end
class Person
include Greetings
end
person = Person.new
puts person.hello # Output: "Hello from instance!"
puts Person.hello # Output: "Hello from class!"