Đặc trưng của module_function vs extend self trong ruby
Bài đăng này đã không được cập nhật trong 5 năm
- Bài viết được dịch từ bài Is module_function really the same as extend self?.
- apidock ruby

Trong bài viết này, chúng ta sẽ khám phá các chủ đề sau:
- Phân biệt giữa
module_functionvàextend self module_functionvsextend self
Nếu như bạn không quen thuộc với khái niệm cơ bản module trong Ruby: đọc Module in Ruby Part I
Giới thiệu
Trong Ruby, một module có thể được sử dụng như một instance logic. Nó nhóm các phương thức ở mức mô-đun lại, mà không sử dụng dựa trên cơ sở mixin - ví dụ: module Base64.
Trong Ruby, có một tập hợp các kỹ thuật để đạt được kết quả mong đợi này. 2 cái được biết đến nhiều nhất là module module_function và extend self.
Hoạt động
Chi tiết sự khác biệt chính giữa 2 cách tiếp cận này là gì?
extend self:
module RubyCademy
extend self
def headline
puts "Learn Ruby and Ruby on Rails!"
end
end
RubyCademy.headline # => Learn Ruby and Ruby on Rails!
Bằng cách extend self trong module RubyCademy, tất cả các instance methods được xác định trong module này sẽ có sẵn ở module level - Đó là lý do tại sao chúng ta có thể gọi RubyCademy.headline.
module_function:
module RubyCademy
def headline
puts "Learn Ruby and Ruby on Rails!"
end
module_function :headline
end
RubyCademy.headline # => Learn Ruby and Ruby on Rails!
Ở đây, chúng ta cũng định nghĩa một instance method RubyCademy#headline. Sau đó, chúng ta gọi module_function :headline. Tại thời điểm này, phương thức headline cũng có sẵn dưới dạng module method - còn được gọi là module function.
extend self vs module_function
Cho đến thời điểm hiện tại, chúng ta đã thấy có 2 cách để khai báo các instance method là module method: extend self và module_ function. Vì vậy, hãy xem điều gì xảy ra ở sâu bên trong để thực sự hiểu sự khác biệt của chúng.
Hiển thị method
module TheDevelopersJourney
extend self
def headline
puts "Thoughts about the life of a developer.."
end
end
class MediumBlog
include TheDevelopersJourney
end
TheDevelopersJourney.singleton_methods.include?(:headline) # => true
MediumBlog.new.public_methods.include?(:headline) # => true
Đầu tiên, chúng ta xác định một module TheDevelopersJourney có chứa một instance method headline. Sau đó, chúng ta tạo một module function headline bằng cách sử dụng cơ chế extend self. Tiếp theo, chúng ta xác định một class MediumBlog, thêm include TheDevelopersJourney . Cuối cùng, chúng ta nhận thấy rằng việc gọi extend self đã phần nào thay đổi loại phương thức:
- một cái
headlinesingleton method đã được thêm vào module TheDevelopersJourney - cái
headlineđược included vào MediumBlog là public method
Còn bây giờ module_function thì sao ?
module RubyCademy
def headline
puts "Learn Ruby and Ruby on Rails!"
end
module_function :headline
end
class Website
include RubyCademy
end
RubyCademy.singleton_methods.include?(:headline) # => true
Website.new.private_methods.include?(:headline) # => true
Đầu tiên, chúng ta xác định một module RubyCademy có chứa một phương thức instance headline. Sau đó, chúng ta tạo ra một module method headline bằng cách sử dụng quy trình module_function. Tiếp theo, chúng ta xác định một class Website bao gồm module RubyCademy. Cuối cùng, chúng ta nhận thấy rằng lệnh gọi tới module_ functions đã thay đổi một phần kiểu phương thức:
- một cái
headlinesingleton method đã được thêm vào module RubyCademy - cái
headlineđược included là private method
Đây là sự khác biệt chính giữa extend self và module_function. Cái sau(module_function) thực sự tạo ra một module function bằng cách hạn chế quyền truy cập vào phương thức được include trong khi extend self vẫn cho phép truy cập vào phương thức được include.
module function copy Một sự khác biệt khác vẫn là sự thật rằng việc extend self và module_ function không generate ra cùng một loại module function
module ModuleFunction
def who_am_i
"ModuleFunction"
end
module_function :who_am_i
end
ModuleFunction.who_am_i # => "ModuleFunction"
module ModuleFunction
def who_am_i
"overriden ModuleFunction"
end
end
ModuleFunction.who_am_i # => "ModuleFunction"
module ModuleFunction
module_function :who_am_i
end
ModuleFunction.who_am_i # => "overriden ModuleFunction"****
- Đầu tiên, chúng ta xác định phương thức: who_am_i là hàm mô-đun bằng cách sử dụng
module_function :who_am_i. - Sau đó, chúng ta ghi đè phương thức này nhưng chúng ta nhận thấy rằng sửa đổi không được áp dụng.
- Cuối cùng, để áp dụng được sửa đổi mong muốn, chúng ta phải gọi lại
module_ function: who_am_i.
Thật vậy, vì module function của chúng ta là bản sao của phương thức instance who_am_i ban đầu, việc sửa đổi của chúng tôi đối với phương thức phiên bản này đương nhiên không được truyền sang module function - trừ khi chúng tôi khai báo lại(copy lại) phương thức instance đã sửa đổi dưới dạng m,odule function bằng cách sử dụng module_ function.
Đừng để xem cách thức extend self hoạt động với instance method bị ghi đè
module ModuleFunction
extend self
def who_am_i
"ModuleFunction"
end
end
ModuleFunction.who_am_i # => "ModuleFunction"
module ModuleFunction
def who_am_i
"overridden ModuleFunction"
end
end
ModuleFunction.who_am_i # => "overridden ModuleFunction"
=> một khi đã extend self => tất cả instance method khai báo tiếp theo sau, hay là bị ghi đè: đều sẽ trở thành method câp độ module của ModuleFunction
Thật vậy, vì module function của chúng ta không phải là bản copy của phương thức instance who_am_i ban đầu, việc sửa đổi của chúng ta đối với phương thức instance được truyền một cách hiển nhiên đến module function.
Ưu điểm
extend self:
- không cần copy method, => meta programming thoải mái
module_function:
- Dễ đọc
- khả năng: Đặt các phương thức được include ở chế độ private là điều kiện tiên quyết của thiết kế module function (nếu muốn).
- sao chép Module function: cơ chế an toàn để tránh ghi đè chức năng mô-đun giúp ngăn ngừa các tác dụng phụ.
kết luận
Bây giờ bạn có các quan điểm để đưa ra quyết định đúng đắn khi nói đến việc tạo một module function ... dùng hay không dùng . 😊
Cuối cùng, thật thú vị khi sử dụng phương pháp này khi các method của bạn độc lập với các đối tượng bên trong - Ví dụ: mô-đun Math.
Lưu ý rằng module_funciton được ứng dụng rất mạnh trong các Thư viện Chuẩn Ruby.
All rights reserved