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:
includeis 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:
extendis 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
includewhen 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
extendwhen 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!"