2009-04-29 10 views

risposta

40
def define_singleton_method_by_proc(obj, name, block) 
    metaclass = class << obj; self; end 
    metaclass.send(:define_method, name, block) 
end 
p = proc { "foobar!" } 
define_singleton_method_by_proc(y, :bar, p) 

o, se si vuole scimmia-patch oggetto per rendere più facile

class Object 
    # note that this method is already defined in Ruby 1.9 
    def define_singleton_method(name, callable = nil, &block) 
    block ||= callable 
    metaclass = class << self; self; end 
    metaclass.send(:define_method, name, block) 
    end 
end 

p = proc { "foobar!" } 
y.define_singleton_method(:bar, p) 
#or 
y.define_singleton_method(:bar) do 
    "foobar!" 
end 

o, se si vuole definire la linea proc, questo può essere più leggibile

class << y 
    define_method(:bar, proc { "foobar!" }) 
end 

o,

class << y 
    define_method(:bar) { "foobar!" } 
end 

questo è il mo st leggibili, ma probabilmente non si adatta alle tue esigenze

def y.bar 
    "goodbye" 
end 

This question is highly related

15

È possibile utilizzare la sintassi class <<object per ottenere "classe singleton" di un oggetto (che è una classe genitore speciale che appartiene solo a quella oggetto) e definire i metodi solo per quell'istanza. Per esempio:

str1 = "Hello" 
str2 = "Foo" 

class <<str1 
    def to_spanish 
    'Hola' 
    end 
end 

Ora, se lo fai str1.to_spanish, tornerà "Hola", ma str2.to_spanish vi darà un'eccezione NoMethodFound.

+0

se ha un proc definito esternamente in una variabile semplice, è difficile inserirlo nel nuovo ambito creato dalla classe << str1, senza ricorrere a variabili globali o di istanza –

19

non sono sicuro di quale versione di Ruby questo è stato aggiunto (almeno 1.8.7), ma sembra che ci sia un modo ancora più semplice per farlo:

str1 = "Hello" 
str2 = "Goodbye" 
def str1.to_spanish 
    "Hola" 
end 
puts str1 # => Hello 
puts str1.to_spanish # => Hola 
puts str2 # => Goodbye 
puts str2.to_spanish # => Throws a NoMethodError 

imparato a conoscere questo mentre la lettura la lezione Ruby Koans (about_class_methods.rb). Non sono ancora del tutto sicuro di quale sia lo scopo di questo, dal momento che mi sembra un po 'pericoloso.

+0

Grazie per aver postato questo (altro) fino a -data di risposta! –

+0

Supponendo che 'str.to_spanish' fosse già definito e volevo" ridefinirlo ", come potrei chiamare" str.to_spanish "" originale "da quello appena definito? –

+0

Se 'str' è il tuo oggetto istanza e' String' è la tua classe, puoi chiamare la versione della classe del metodo da 'String.to_spanish' – BRFennPocock

Problemi correlati