2016-10-06 4 views
1

ich einen Methodennamen übergeben wollen, kein Block, als Parameter an eine andere Methode als Callback zu verwenden:Pass Methodennamen als Parameter an eine andere Methode

def one(param) 
    puts param 
end 

def two(param, &callback) 
    callback.call(param) 
end 

two('hi', :one) 

Ist das möglich? Ich habe es versucht und einen Fehler bekommen, indem ich sagte, dass ich zwei Parameter übergeben habe, aber nur einer erwartet wurde.

+0

Nur eine wurde erwartet, da & Callback kein Parameter ist. – MageeWorld

Antwort

1

Sie wollen send verwenden:

def two(param, callback) 
    send(callback, param) 
end 
+1

Bitte verwenden Sie stattdessen 'public_send'. –

1

Während @ JohnNaegle Antwort richtig ist, finde ich diese eine etwas elegantere Weg, dies zu tun, ist #method verwenden, die eine Method Objekt zurückgibt. Das Methodenobjekt verfügt über eine .call(*args)-Methode, über die Sie Argumente übergeben können. Also, mit Ihrem Beispiel würde es wie folgt aussehen:

def one(param) 
    puts param 
end 

def two(param, callback) 
    callback.call(param) 
end 

two('hi', method(:one)) 

Die Änderung ist, dass Sie einen Verweis auf eine Instanz Method sind vorbei durch den Aufruf Object.method (elbe wie method), anstatt einen String.

Wenn Sie statt eines Method ein Symbol übergeben Sie die folgende Version von #two verwenden:

def two_2(param, callback) 
    method(callback.to_sym).call(param) 
end 

two_2('hi', :one) 
# Or you could also pass a string or anything that #responds_to?(:to_sym) 
two_2('hi', 'one') 

Eine weitere Verbesserung würde ich empfehlen, so dass two kann mehr als einen Parameter akzeptieren, um einen Pass zu spielen Der Rückruf würde zuerst den Rückruf auflisten und dann *params verwenden, um so viele Parameter wie nötig zu empfangen. Hier ist ein Beispiel (mit Definition von #one von oben):

def one_with_many_params(*params) 
    puts params.join 
end 

# Improved version of two 
def two_3(callback, *params) 
    callback.call(params) 
end 

# Improved version of two_2 
def two_4(callback, *params) 
    method(callback.to_sym).call(params) 
end 

two_3(method(:one), 'hi') #=> "hi" 
two_3(method(:one_with_many_params), "Hi", " my ", "name", " is ", "Foo!") 
#=> "Hi my name is Foo!" 

two_4('one', 'Hello!') #=> "Hello!" 
two_4(:one_with_many_params, "Hi", " my ", "name", " is ", "Bar!") 
#=> "Hi my name is Bar!" 
3

Wenn Sie den Namen ein Verfahren senden wollen, dann, ja, ein Symbol ist die richtige Form für das, wie John Antwort Punkte out (und Sie können dann senden verwenden, um diese Methode aufzurufen). Aber, wenn Sie möchten, können Sie auch die Methode senden selbst:

def one(param) 
    puts param 
end 

def two(param, &callback) 
    callback.call(param) 
end 

one_method = method(:one) 
two('hi', &one_method) 

Der Vorteil dieser Art und Weise, Dinge zu tun, ist, dass Sie es tun können, wenn ein Verfahren zur Herstellung eines Block erwartet, ohne (wie two tun) ohne die Methodendefinition zu ändern. Sie können auch Methoden von verschiedenen Objekten übergeben, während Sie mit send, wenn Sie die Methode für ein anderes Objekt aufrufen möchten, auch angeben müssen, wen Sie aufrufen möchten (oder auf andere Weise herausfinden):

class Foo 
    def one(param) 
    puts param 
    end 
end 

class Bar 
    def two(param, &callback) 
    callback.call(param) 
    end 
end 

f = Foo.new 
b = Bar.new 
b.two('hi') {|param| puts param } # with a block 
b.two('hi', &f.method(:one)) # with a Method object 
Verwandte Themen