Tôi đã cố gắng tìm hiểu cách mở rộng hành vi của initialize
từ mô-đun. Tôi muốn làm điều đó mà không cần gọi siêu trong số initialize
của lớp đang được trộn vào. Tôi muốn hỗ trợ kiểu gọi thông thường include
Tôi không thể hiểu được. Tôi đã đọc tất cả mọi thứ tôi có thể tìm thấy về vấn đề này và, trong khi mọi người có đề xuất, không ai trong số họ thực sự có vẻ làm việc (trong tay tôi ít nhất).Có thể ghi đè #initialize trong mô-đun Ruby không?
Dưới đây là những gì tôi (nghĩ) Tôi biết:
- Nếu nó có thể được thực hiện ở tất cả, nó phải được thực hiện bằng cách sử dụng móc trên
include
(ví dụ:Module.included(base)
). - Móc
include
sẽ thực thi trước khi lớp bao gồm xác địnhinitialize
do đó không có điểm để chỉ đơn giản là cố gắng xác địnhinitialize
vớibase.instance_eval
vì nó sẽ bị ghi đè. Một đề xuất đã được thực hiện để sử dụng móc
method_added
và xử lý nó trong đó. Đó là những gì tôi đang thử bây giờ nhưng có vẻ như móc thực hiện ở đầu định nghĩa phương thức để bạn kết thúc với những gì bạn thấy bên dưới.module Mo def self.included(klass) klass.instance_eval do def method_added(method) puts "Starting creation of #{method} for #{self.name}" case method when :initialize alias_method :original_initialize, :initialize puts "About to define initialize in Mo" def initialize original_initialize puts "Hello from Mo#initialize" end puts "Finished defining initialize in Mo" end puts "Finishing creation of #{method} for #{self.name}" end end end end class Foo include Mo def initialize puts "Hello from Foo#initialize" end end foo = Foo.new
Điều này dẫn đến kết quả như sau:
Starting creation of initialize for Foo
Starting creation of original_initialize for Foo
Finishing creation of original_initialize for Foo
About to define initialize in Mo
Finished defining initialize in Mo
Finishing creation of initialize for Foo
Hello from Foo#initialize
Có vẻ với tôi như initialize
từ lớp Foo vẫn ghi đè lên các định nghĩa từ các mô-đun. Tôi đoán rằng điều này là bởi vì định nghĩa vẫn còn mở, cho thấy rằng nó không phải là vấn đề mà khối được bắt đầu cuối cùng được hoàn thành cuối cùng mà "thắng".
Nếu có ai đó thực sự biết cách làm điều này và làm việc đó, hãy làm sáng tỏ tôi.
FWIW, vâng, tôi nghĩ tôi có lý do chính đáng để làm điều này.
Tôi phát hiện ra 'prepend' ngay sau khi đặt câu hỏi. Tôi thích nó! Vẫn còn tò mò nếu có một cách để làm điều đó trong 1.9. * – Huliax
Có điều gì hiển nhiên tôi thiếu trong việc sử dụng 'klass.send: prepend' thay vì đơn giản' klass.prepend'? – NobodysNightmare