Scroll to top
Tìm hiểu về include, prepend, extend trong Ruby

Tìm hiểu về include, prepend, extend trong Ruby

ByYuto 12/10/2024 01:10
6min read

Trong Ruby, việc sử dụng include, prepend và extend là các kỹ thuật quan trọng giúp bạn có thể tận dụng tối đa tính năng module. Hãy cùng tìm hiểu chi tiết về từng phương pháp và cách sử dụng chúng với các ví dụ minh họa dễ hiểu.

Có 3 cách thường thấy để đưa một module vào một class, đó là include, prependextend. Trong bài viết này chúng ta sẽ tìm hiểu và so sánh sự giống và khác nhau của 3 khái niệm trên.

include trong Ruby

include là cách phổ biến nhất để import code từ một module khác vào class, include thêm các method của một module vào một class như là các instance methods. Điều này có nghĩa là bạn có thể gọi các method này trên các đối tượng của lớp đó.

Ví dụ về include

ruby
Copy
1
2
3
4
5
6
7
8
9
10
11
12
module Greetings
  def greet
    puts "Hello world!"
  end
end

class Person
  include Greetings
end

person = Person.new
person.greet # Output: "Hello world!"

ancestors chain khi include module vào class

Khi ta include một module vào một class, thì module đó sẽ được thêm vào ancestors chain của class đó, vị trí là ngay sau chính class đó và trước super class của class đó.

Khi ta kiểm tra ancestors chain của ví dụ trên thì sẽ thấy như sau:

ruby
Copy
1
2
Person.ancestors
# => [Person, Greetings, Object, Kernel, BasicObject]

Module Greetings được thêm vào ancestors chain, ngay sau class Person và trước super class Object.

Trường hợp include nhiều module thì ancestors chain sẽ như thế nào?

Ví dụ đoạn code sau:

ruby
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module Greetings
  def greet
    puts "Hello world!"
  end
end

module Working
  def work
    puts "Working..."
  end
end

class Person
  include Greetings
  include Working
end

Lúc này khi ta kiểm tra Person.ancestors thì sẽ thấy kết quả như sau:

ruby
Copy
1
[Person, Working, Greetings, Object, Kernel, BasicObject]

Module được include sau thì sẽ gần với class đó hơn, tóm lại, nếu 2 module được include vào có cùng một method, thì method ở module được include sau sẽ được ưu tiên thực hiện. Điều này có nghĩa là thứ tự include rất quan trọng vì nó xác định method nào sẽ được gọi nếu có sự xung đột tên method.

prepend trong Ruby

prepend có từ Ruby phiên bản 2.0, mặc dù ít được dùng hơn so với includeextend.

Về bản chất thì prepend tương tự include, điểm khác biệt là ở chỗ prepend sẽ thêm module đó vào trước class trong ancestors chain. Đồng nghĩa với việc nếu module dược prepend và class đều có cùng một method giống nhau, thì method ở module được prepend sau cùng sẽ được ưu tiên thực hiện.

Ví dụ về prepend

ruby
Copy
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 greet
    puts "Hello world!"
  end
end

module Working
  def greet
    puts "Working..."
  end
end

class Person
  prepend Greetings
  include Working

  def greet
    puts "Hi"
  end

  person = Person.new
  person.greet # Output: "Hello world!"
end

Lúc này khi ta kiểm tra Person.ancestors thì sẽ thấy kết quả như sau:

ruby
Copy
1
[Greetings, Person, Working, Object, Kernel, BasicObject]

Như các bạn thấy, module được prepend sẽ xếp đầu tiên, tiếp theo đó là class rồi mới đến module được include.

extend trong Ruby

extend khác với includeprepend, khi ta extend module vào một class, thì những method của module đó sẽ được import vào như là class method, chứ không phải là instance method.

extend module vào class sẽ không thêm module đó vào ancestors chain của class.

Ví dụ về extend

ruby
Copy
1
2
3
4
5
6
7
8
9
10
11
module Greetings
  def greet
    "Hello world!"
  end
end

class Person
  extend Greetings
end

puts Person.greet # Output: "Hello world!"

Ở đây, module Greetings được extend vào class Person, và method greet trở thành một class method của Person.

Tổng kết

Trong Ruby, ba phương thức include, extend, và prepend được sử dụng để thêm các phương thức của module vào class hoặc đối tượng. Mỗi phương thức có cách hoạt động và mục đích sử dụng riêng. Đây là bảng tóm tắt so sánh về các phương thức này:

Phương thức Mô tả
include * Định nghĩa các method của module như là các instance method.
* Nếu đã có method cùng tên trong class, method của class sẽ được ưu tiên gọi.
* Module được include sau sẽ nằm gần class hơn trong ancestors chain và method của nó sẽ được ưu tiên gọi hơn nếu có xung đột tên method.
prepend * Chèn module vào đầu ancestors chain, các method của module được định nghĩa như là các instance method.
* Nếu đã có method cùng tên trong class, method của module sẽ được ưu tiên gọi hơn.
extend * Các method được định nghĩa trong module có thể được sử dụng như là các class method.
* Sẽ không thêm module đó vào ancestors chain của class.

Việc nắm vững cách sử dụng các phương thức này sẽ giúp bạn tổ chức mã nguồn một cách hiệu quả và linh hoạt hơn trong các dự án Ruby của mình. Hãy thử nghiệm và áp dụng chúng để tận dụng tối đa khả năng của Ruby!

Đánh giá bài viết: 5/5 (39 đánh giá)
Bạn chưa đánh giá

Bình luận

Author
hoclaptrinh.io author
Tác giả:Yuto Yasunaga

Mình là một full stack developer, tốt nghiệp và làm việc tại Nhật Bản. Trang web này là nơi mình tổng hợp, đúc kết và lưu trữ lại những kiến thức trong quá trình học và làm việc liên quan đến IT.
Hy vọng những bài viết ở website này sẽ có ích cho bạn.