2010-04-20 100 views
2

我有以下代碼:瞭解Ruby類VS實例方法

#!/usr/bin/ruby 

class Person 
    def self.speak 
    p = self.new 
    puts "Hello" 
    p.chatter 
    end 

private 

    def chatter 
    puts "Chattering" 
    end 
end 

p = Person.new 
Person.speak 

我想提出喋喋不休私人,只有在p訪問..但我想p來能夠在類內訪問方法。有沒有更好的方法來設計這個,所以聊天不公開,但像self.speak這樣的「工廠」方法可以調用聊天?

回答

8

在Ruby 1.8.7, 「發送」 繞過通常的保護措施,當調用私有方法:

#!/usr/bin/ruby1.8 

class Person 

    def self.speak 
    puts "Hello" 
    new.send(:chatter) 
    end 

    def speak 
    puts "Hello" 
    puts chatter 
    end 

    private 

    def chatter 
    puts "Chattering" 
    end 

end 

Person.speak  # => Hello 
        # => Chattering 
Person.new.speak # => Hello 
        # => Chattering 

然而,你想要什麼都可以在沒有任何巫術的情況下實現,只需要使用類方法完成所有工作,並且實例方法遵循類方法:

class Person 

    def self.speak 
    puts "Hello" 
    puts "Chatter" 
    end 

    def speak 
    self.class.speak 
    end 

end 

如果你有以上幾個這些轉發方法的更多,這可能是方便做一個輔助方法,讓他們爲你:

module DelegateToClass 

    def delegate_to_class(name) 
    define_method(name) do |*args| 
     self.class.send(name, *args) 
    end 
    end 

end 

class Person 

    extend DelegateToClass 

    def self.speak 
    puts "Hello" 
    puts "Chatter" 
    end 
    delegate_to_class :speak 

end 

內置模塊Forwardable可以只是這樣做以及:

require 'forwardable' 

class Person 

    extend Forwardable 

    def self.speak 
    puts "Hello" 
    puts "Chatter" 
    end 

    def_delegator self, :speak 

end 

def_delegator也繞過對私人方法的保護。

+0

不錯的解決方案,雖然我有這樣的感覺,即如果OP必須訴諸這樣的技巧,那麼設計中會出現更根本性的錯誤。 – 2010-04-20 13:24:15

+1

@JörgW Mittag,我同意。這可能是一種跡象,表明這種方法實際上不會搬出去,找到工作,並在自己的單元或班級中安頓下來。 – 2010-04-20 13:58:19

1

有很多方法可以做到這一點。一種方法是實例化新實例並在實例上調用#speak方法的類方法。

class Person 
    def self.speak 
    new.speak 
    end 

    def speak 
    puts "Hello" 
    chatter 
    end 

    private 

    def chatter 
    puts "Chattering" 
    end 
end 

然後,你可以把它在任何類或實例背景:

p = Person.new 
p.speak 
# ...or... 
Person.speak