2017-06-22 31 views
0

在包含模塊的同時,是否有簡明的方法來限制模塊內的方法可見性?換句話說,我想用僅包含模塊中使用的輔助方法來限制污染類。在包含模塊時避免類污染

module Bar 
    def call 
    hide_me 
    end 

    private 

    # make this method only callable within this module 
    def hide_me 
    'visible' 
    end 
end 

class Foo 
    include Bar 

    def unrelated_method 
    hide_me 
    end 
end 

# that's ok 
Foo.new.call #=> 'visible' 

# that's not 
Foo.new.unrelated_method #=> 'visible' 

我確定通過Bar.instance_method(:hide_me).bind(self).call調用它,我只是不想擔心一些模塊來訪問或重新定義一個輔助方法。通過包括模塊類,然後取消定義不需要包括方法

module Bar 

    def call 
    BarClass.new.call 
    end 

    class BarClass 
    def call 
     hide_me 
    end 

    private 

    def hide_me 
     puts "invisible" 
    end 

    end 

end 

class Foo 

    include Bar 

    def call_bar 
    call 
    end 

    def this_method_fails 
    hide_me 
    end 

end 

回答

2

你可以用一個類到模塊和類中使用私有方法,像這樣。

首先構建一個模塊。

module M 
    def cat 
    puts "meow" 
    end 
    def dog 
    puts "woof" 
    end 
    def owl 
    puts "who?" 
    end 

    private 

    def frog 
    puts "ribbit" 
    end 
    def pig 
    puts "oink" 
    end 
end 

確認現在存在的方法。

M.instance_methods(false) 
    #=> [:cat, :dog, :owl] 
M.private_instance_methods(false) 
    #=> [:frog, :pig] 

創建該類,包括模塊M

class C 
    def froggie 
    frog 
    end 
    def cat 
    puts "meow-meow" 
    end 
    include M 
end 

檢查實例方法。

C.instance_methods & [:cat, :dog, :owl, :froggie] 
    #=> [:cat, :froggie, :dog, :owl] 
C.private_instance_methods & [:frog, :pig] 
    #=> [:frog, :pig] 

,並確認:catC而不是M擁有。

C.instance_method(:cat).owner 
    #=> C 

現在使用的方法Module#undef_method取消定義從模塊不需要的方法。

class C 
    [:cat, :owl, :pig].each { |m| 
    undef_method(m) unless instance_method(m).owner == self } 
end 

是需要的unless...子句使得實例方法:catC定義不是未定義。

確認方法未定義。

C.instance_methods & [[:cat, :dog, :owl, :froggie] 
    #=> [:cat, :froggie, :dog] 
C.private_instance_methods & [:frog, :pig] 
    #=> [:frog] 

執行方法。

c = C.new 
c.cat 
    #=> "meow-meow" 
c.dog 
    #=> "woof" 
c.froggie 
    #=> "ribbit" 
+0

這似乎是最乾淨的方式,謝謝! –

0

一個可以做你想做什麼:

+0

它的工作原理,但要求你確切地知道什麼方法取消定義,並需要在課堂上額外的代碼。有點太凌亂 –

+0

你顯然需要知道哪個模塊的實例方法將被使用或哪些不被使用,並且可以很容易地從另一個方法中計算出一個:'used_public_instance_methods +