2011-06-29 24 views
14

Tôi có một mô-đun của saucủa Ruby bao gồm phương pháp duy nhất của module trong mô hình

module SimpleTask 
    def task1 
    end 
    def task2 
    end 
    def task3 
    end 
end 

Và tôi có một mô hình mà chỉ đòi hỏi task2 phương pháp mô-đun SimpleTask.

Tôi biết bao gồm SimpleTask trong mô hình của mình với include SimpleTask sẽ thực hiện công việc.

Nhưng tôi tự hỏi liệu mình có thể chỉ bao gồm phương thức task2 cụ thể trong mô hình của mình hay không.

+0

có thể trùng lặp của [Tôi có thể gọi phương thức thể hiện trên mô-đun Ruby mà không bao gồm nó không?] (Http://stackoverflow.com/questions/322470/can-i-invoke-an-instance-method-on-a -ruby-module-without-includes-it) –

Trả lời

6

Có vẻ như bạn cần phải cấu trúc lại #task2 thành một mô-đun riêng biệt (ví dụ: BaseTask). Sau đó, bạn có thể dễ dàng chỉ bao gồm BaseTask nơi bạn chỉ cần #task2.

module BaseTask 
    def task2 
    ... 
    end 
end 

module SimpleTask 
    include BaseTask 

    def task1 
    ... 
    end 

    def task3 
    ... 
    end 
end 

Thật khó để giúp đỡ nhiều hơn nữa mà không có một câu hỏi cụ thể hơn (ví dụ như phụ thuộc lẫn nhau giữa các phương pháp SimpleTask vv

Bạn thể làm một số meta-lập trình, nơi bạn include SimpleTask và sau đó undefine sự phương pháp mà bạn không muốn, nhưng đó là khá xấu xí IMO.

3

bạn có thể thêm

module SimpleTask 
    def task1 
    end 
    def task2 
    end 
    def task3 
    end 
    module_function :task2 
end 

Vì vậy mà bạn có thể gọi phương thức như một phương pháp học trên mô-đun cũng như có nó như là một phương pháp dụ ở các vị trí bạn làm muốn cả ba phương pháp, ví dụ:

class Foo 
    include SimpleTask 
end #=> Foo.new.task2 
class LessFoo 
    def only_needs_the_one_method 
     SimpleTask.task2 
    end 
end #=> LessFoo.new.only_needs_the_one_method 

Hoặc, nếu thực sự không có trạng thái chia sẻ nào trong mô-đun và bạn không nhớ luôn sử dụng tên mô-đun chính nó, bạn chỉ có thể khai báo tất cả các phương thức cấp lớp như vậy:

module SimpleTask 
    def self.task1 
    end 
    def self.task2 
    end 
    def self.task3 
    end 
end 

class Foo 
    include SimpleTask # Does, more or less nothing now 
    def do_something 
    SimpleTask.task1 
    end 
end 
#=> Foo.new.task2 #=> "task2 not a method or variable in Foo" 
#=> Foo.new.do_something does, however, work 
class LessFoo 
    def only_needs_the_one_method 
     SimpleTask.task2 
    end 
end #=> LessFoo.new.only_needs_the_one_method works as well in this case 

Nhưng bạn phải thay đổi tất cả người gọi trong trường hợp đó.

5

Tôi sẽ ăn cắp một ví dụ từ delegate.rb, nó hạn chế những gì nó bao gồm

... 
class Delegator < BasicObject 
    kernel = ::Kernel.dup 
    kernel.class_eval do 
    [:to_s,:inspect,:=~,:!~,:===,:<=>,:eql?,:hash].each do |m| 
     undef_method m 
    end 
    end 
    include kernel 
... 

trở thành

module PreciseInclude 

    def include_except(mod, *except) 
    the_module = mod.dup 
    the_module.class_eval do 
     except.each do |m| 
     remove_method m # was undef_method, that prevents parent calls 
     end 
    end 
    include the_module 
    end 
end 

class Foo 
    extend PreciseInclude 

    include_except(SimpleTask, :task1, :task2) 
end 

Foo.instance_methods.grep(/task/) => [:task3] 

bạn luôn có thể lật nó nên thay vì đưa nó trở thành include_only

Việc nắm bắt là remove_method sẽ không hoạt động đối với các mô đun lồng nhau và việc sử dụng undef sẽ ngăn không cho tìm kiếm toàn bộ hệ thống phân cấp cho phương thức đó.

Các vấn đề liên quan