2010-04-20 4 views
2

Je le code suivant:classe Comprendre Ruby vs méthodes d'instance

#!/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 

Je voudrais faire bavardage privé, accessible seulement à l'intérieur p .. mais je veux p pour pouvoir accéder à l'intérieur de la classe méthode. Y a-t-il une meilleure façon de concevoir ceci afin que le bavardage ne soit pas disponible au public, mais une méthode "d'usine" comme self.speak peut appeler le bavardage?

Répondre

8

Dans Ruby 1.8.7, "envoyer" contourne les protections habituelles contre l'appel de méthodes privées:

#!/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 

Cependant, ce que vous voulez peut être réalisé sans n'importe quel vaudou, en ayant simplement la méthode de classe faire tout le travail, et la méthode d'instance différer à la méthode de classe:

class Person 

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

    def speak 
    self.class.speak 
    end 

end 

Si vous aviez plus de certaines de ces méthodes d'acheminement, il peut être pratique de faire une méthode d'assistance qui les rend pour vous:

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 

Le module intégré Forwardable peut faire juste ainsi:

require 'forwardable' 

class Person 

    extend Forwardable 

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

    def_delegator self, :speak 

end 

def_delegator contourne également des protections contre des méthodes privées.

+0

Belle solution, bien que j'ai l'impression que si l'OP doit recourir à de telles astuces, il y a quelque chose de beaucoup plus fondamentalement faux avec le design. –

+1

@ Jörg W Mittag, je suis d'accord. Cela peut être un signe que la méthode est vraiment là pour sortir, trouver un emploi et s'installer dans son propre module ou classe. –

1

Il y a un certain nombre de façons de le faire. Une approche serait une méthode de classe qui instancie une nouvelle instance et appelle la méthode #speak sur l'instance.

class Person 
    def self.speak 
    new.speak 
    end 

    def speak 
    puts "Hello" 
    chatter 
    end 

    private 

    def chatter 
    puts "Chattering" 
    end 
end 

Ensuite, vous pouvez l'appeler soit dans le contexte de la classe ou de l'instance:

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