it-swarm.com.de

Wie übergeben Sie Argumente an define_method?

Ich möchte ein oder mehrere Argumente an eine Methode übergeben, die mit define_method definiert wird. Wie würde ich das tun?

150
Sixty4Bit

Der Block, den Sie an define_method übergeben, kann einige Parameter enthalten. So akzeptiert Ihre definierte Methode Argumente. Wenn Sie eine Methode definieren, benennen Sie den Block nur kurz und behalten einen Verweis darauf in der Klasse. Die Parameter liegen dem Baustein bei. So:

define_method(:say_hi) { |other| puts "Hi, " + other }
188
Kevin Conner

... und wenn Sie optionale Parameter wünschen

 class Bar
   define_method(:foo) do |arg=nil|                  
     arg                                                                                          
   end   
 end

 a = Bar.new
 a.foo
 #=> nil
 a.foo 1
 # => 1

... so viele Argumente wie Sie wollen

 class Bar
   define_method(:foo) do |*arg|                  
     arg                                                                                          
   end   
 end

 a = Bar.new
 a.foo
 #=> []
 a.foo 1
 # => [1]
 a.foo 1, 2 , 'AAA'
 # => [1, 2, 'AAA']

...Kombination von

 class Bar
   define_method(:foo) do |bubla,*arg|
     p bubla                  
     p arg                                                                                          
   end   
 end

 a = Bar.new
 a.foo
 #=> wrong number of arguments (0 for 1)
 a.foo 1
 # 1
 # []

 a.foo 1, 2 ,3 ,4
 # 1
 # [2,3,4]

... alle von ihnen

 class Bar
   define_method(:foo) do |variable1, variable2,*arg, &block|  
     p  variable1     
     p  variable2
     p  arg
     p  block.inspect                                                                              
   end   
 end
 a = Bar.new      
 a.foo :one, 'two', :three, 4, 5 do
   'six'
 end

Update

Ruby 2.0 hat Double Splat ** (Zwei Sterne) eingeführt, das ( ich zitiere ) Folgendes bewirkt:

Ruby 2.0 führte Schlüsselwortargumente ein und ** verhält sich wie *, nur für Schlüsselwortargumente. Es wird ein Hash mit Schlüssel/Wert-Paaren zurückgegeben.

... und natürlich können Sie es auch in define-Methode verwenden :)

 class Bar 
   define_method(:foo) do |variable1, variable2,*arg,**options, &block|
     p  variable1
     p  variable2
     p  arg
     p  options
     p  block.inspect
   end 
 end 
 a = Bar.new
 a.foo :one, 'two', :three, 4, 5, Ruby: 'is awesome', foo: :bar do
   'six'
 end
# :one
# "two"
# [:three, 4, 5]
# {:Ruby=>"is awesome", :foo=>:bar}

Beispiel für benannte Attribute:

 class Bar
   define_method(:foo) do |variable1, color: 'blue', **other_options, &block|
     p  variable1
     p  color
     p  other_options
     p  block.inspect
   end
 end
 a = Bar.new
 a.foo :one, color: 'red', Ruby: 'is awesome', foo: :bar do
   'six'
 end
# :one
# "red"
# {:Ruby=>"is awesome", :foo=>:bar}

Ich habe versucht, ein Beispiel mit dem Schlüsselwort argument, splat und double splat in einem zu erstellen:

 define_method(:foo) do |variable1, variable2,*arg, i_will_not: 'work', **options, &block|
    # ...

oder

 define_method(:foo) do |variable1, variable2, i_will_not: 'work', *arg, **options, &block|
    # ...

... aber das wird nicht funktionieren, es scheint eine Einschränkung zu geben. Wenn Sie darüber nachdenken, ist es sinnvoll, dass der splat-Operator "alle verbleibenden Argumente erfasst" und Double splat "alle verbleibenden Schlüsselwortargumente erfasst", sodass das Mischen dieser Argumente die erwartete Logik verletzt. (Ich habe keinen Hinweis, um diesen Punkt zu beweisen, doh!)

Update August 2018:

Zusammenfassender Artikel: https://blog.eq8.eu/til/metaprogramming-Ruby-examples.html

84
equivalent8

Zusätzlich zu Kevin Conners Antwort: Blockargumente unterstützen nicht dieselbe Semantik wie Methodenargumente. Sie können keine Standardargumente oder Blockargumente definieren.

Dies ist nur in Ruby 1.9 mit der neuen alternativen "stabby lambda" -Syntax behoben, die die vollständige Semantik der Methodenargumente unterstützt.

Beispiel:

# Works
def meth(default = :foo, *splat, &block) puts 'Bar'; end

# Doesn't work
define_method :meth { |default = :foo, *splat, &block| puts 'Bar' }

# This works in Ruby 1.9 (modulo typos, I don't actually have it installed)
define_method :meth, ->(default = :foo, *splat, &block) { puts 'Bar' }
59
Jörg W Mittag

Mit 2.2 können Sie jetzt Schlüsselwortargumente verwenden: https://robots.thoughtbot.com/Ruby-2-keyword-arguments

define_method(:method) do |refresh: false|
  ..........
end
7
akostadinov