2013-08-29 38 views
5

Tôi đang cố gắng tạo các phương thức trợ giúp riêng cho các chức năng mô-đun không có kết quả. Tôi cảm thấy như có một cái gì đó rất đơn giản tôi đang mất tích.Truy cập các phương thức riêng tư từ các chức năng mô-đun trong Ruby

dụ cập nhật với một trường hợp sử dụng dễ hiểu hơn:

module FancyScorer 
    module_function 

    def score(ary) 
    scores = [] 
    ary.each_slice(2).with_index do |slice, i| 
     scores << 
     case i % 2 
     when 0 
      score_eventh(ary) 
     else 
      score_oddth(ary) 
     end 
    end 
    scores.inject(:+) 
    end 

    private 

    def score_eventh(ary) 
    ary.inject(:+)/(ary.size - 1) 
    end 

    def score_oddth(ary) 
    ary.inject(:*)/(ary.size - 1) 
    end 
end 

FancyScorer.score([1,2,3,4]) 
# => `block in score_curiously': undefined method `score_eventh' 
# for FancyScorer:Module (NoMethodError) 

Lưu ý: Các phương pháp riêng nên vẫn tin.

Đây là trường hợp sử dụng: có một số mô-đun có chứa các kỹ thuật tính điểm khác nhau, ví dụ: FancyScorer, SimpleScorer, ComplexScorer. Các hàm này được kiểm tra độc lập và sau đó được sử dụng để tạo phương thức score cho các lớp khác nhau. Ví dụ:

class A 
    ... 
    def score  
    FancyScorer.score(metrics) + 2*SimpleScorer.score(metrics) 
    end 
end 

class B 
    ... 
    def score 
    0.5*FancyScorer.score(metrics) + 2*SimpleScorer.score(metrics[0,3]) + ComplexScorer.score(metrics) 
    end 
end 

dụ trước không có trường hợp sử dụng cung cấp:

module Party 
    module_function 

    def pooper 
    enjoy 
    end 

    private 

    def enjoy 
    puts "Wahoo!" 
    end 
end 

Party.pooper 
# => NameError: undefined local variable or method `enjoy' for Party:module 
#   from (party): in `pooper` 
+0

Bạn có một chút của một [XY vấn đề] (http://www.perlmonks.org/?node_id=542341) ở đây. Bạn nên giải thích vấn đề thực tế của bạn. Việc gọi các phương thức trực tiếp trên mô-đun là không bình thường. – naomik

+0

Ví dụ được trình bày là rất giả tạo. Tôi đang triển khai mẫu thiết kế được Corey Haines và Gary Bernhardt quảng bá (cái mà Bernhardt gọi là "lõi chức năng và vỏ bắt buộc"), và trong một số trường hợp, tôi yêu cầu không gian tên để tránh xung đột. – fny

+0

@faraz Bạn đã nhận? –

Trả lời

8

module_function(symbol, ...) → self nói: -

Tạo chức năng mô-đun cho các phương thức đã đặt tên. Các chức năng này có thể được gọi với mô-đun làm người nhận, và cũng có sẵn dưới dạng phương thức mẫu cho các lớp kết hợp trong mô-đun. Các chức năng của mô-đun là bản sao của bản gốc và do đó có thể được thay đổi độc lập. Các phiên bản phương thức cá thể được đặt ở chế độ riêng tư. Nếu được sử dụng không có đối số, các phương thức được định nghĩa sau đó sẽ trở thành các hàm mô-đun.

Bạn cần đảm bảo bạn khai báo phương thức trợ giúp dưới dạng #private_class_method: private chỉ ảnh hưởng đến các phương pháp thể hiện.

module Party 

    def enjoy 
    puts 'hello' 
    end 

    def pooper 
    enjoy 
    end 

    private_class_method :enjoy 
    module_function :pooper 
end 

Party.pooper # => 'hello' 
Party.enjoy # => private method `enjoy' called for Party:Module (NoMethodError) 

Bên cạnh đó, bạn nên cẩn thận về Trật tự của các từ khóa như khả năng tiếp cận public, private, và module_function. Chúng không trùng lặp, nhưng thay vì ghi đè lên.

module Party 
    module_function # Module function declarations begin 
    def pooper 
    bar 
    end 
    def bar 
    enjoy 
    end 

    private   # Private declarations begin, module function declarations end 
    module_function # Private declarations end, module function declarations begin 
    def enjoy  # Therefore, this is a module function 
    "Wahoo!" 
    end 
end 

Party.pooper # => "Wahoo!" 
Party.bar # => "Wahoo!" 
Party.enjoy # => "Wahoo!" <-- No longer private 

Lưu ý đây module_function đè private tuyên bố lúc trước.


Dưới đây một số ví dụ khác khi module_function sẽ làm công việc của mình, và khi không.

Định nghĩa module_function dừng lại khi một từ khóa trợ năng khác bật lên. Trong ví dụ này, module_function bị gián đoạn bởi public làm #pooper phương thức công khai. Sử dụng private tương tự sẽ chặn module_method.

module Party 
    module_function 
    public 
    def pooper 
    "i am pooper" 
    end 
end 

Party.pooper 
# undefined method `pooper' for Party:Module (NoMethodError) 

Bây giờ nếu lệnh được thay đổi:

module Party 
    public 
    module_function 
    def pooper 
    "i am pooper" 
    end 
end 

Party.pooper # => "i am pooper" 
+0

Tôi thậm chí không nhận thức được một 'Module # module_function' nhưng tôi không thể nói rằng tôi ngạc nhiên. Đây là một giải pháp làm việc, nhưng nó có vẻ như thành phần mô-đun rất xấu. (ps. Tôi hiểu đây không phải là lỗi của bạn vì đây là những gì OP yêu cầu) – naomik

+0

@naomik 'module_function' rất thú vị .. hãy đọc tài liệu, bạn có thể hiểu tại sao phương pháp này lại có nhiều hương vị .. –

+0

sau khi đọc tài liệu, tôi thậm chí còn sợ nó hơn bây giờ. 'module_function' có vẻ như là một cách tuyệt vời để phân mảnh tính nhất quán của hành vi của mô-đun của bạn và thêm đống phức tạp. Tôi phải có một lý do thuyết phục thực sự để sử dụng nó. – naomik

2

Nếu bạn muốn gọi phương pháp trực tiếp trên các module (ví dụ, Party.pooper), bạn phải xác định phương pháp sử dụng self

module Party 
    def self.pooper 
    enjoy 
    end 

    private 

    def self.enjoy 
    puts "wahoo!" 
    end 
end 

Party.pooper #=> wahoo! 

Thông thường, một mục đích chính của mô-đun là chúng được thêm vào một lớp học bằng cách sử dụng include hoặc extend.

module Party 
    def pooper 
    enjoy 
    end 

    private 

    def enjoy 
    puts "wahoo!" 
    end 
end 

Dưới đây là một ví dụ extend cho thấy các phương pháp mô-đun được thêm vào như là phương pháp lớp

class Diaper 
    extend Party 
end 

Diaper.pooper #=> wahoo! 

Dưới đây là một ví dụ include cho thấy các phương pháp mô-đun được thêm vào như là phương pháp dụ

class Toilet 
    include Party 
end 

t = Toilet.new 
t.pooper #=> wahoo! 
+0

OP muốn xem về 'module_function' .. Tôi nghĩ bạn đang đi sai đường .. Điều này chưa được hỏi .. –

+1

Có thể, tôi nghĩ có nhiều khả năng OP có [Vấn đề XY] (http: // www.perlmonks.org/?node_id=542341) và không hiểu cách sử dụng mô-đun đúng cách. – naomik

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