Yanıtlar:
Define_method dosyasına ilettiğiniz blok bazı parametreler içerebilir. Tanımlanmış yönteminiz bu şekilde argümanları kabul eder. Bir yöntem tanımladığınızda, gerçekten sadece bloğu takma ve sınıfta bir referans tutma. Parametreler blok ile birlikte gelir. Yani:
define_method(:say_hi) { |other| puts "Hi, " + other }
... ve isteğe bağlı parametreler istiyorsanız
class Bar
define_method(:foo) do |arg=nil|
arg
end
end
a = Bar.new
a.foo
#=> nil
a.foo 1
# => 1
... istediğiniz kadar argüman
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']
...kombinasyonu
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]
... hepsi
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
Güncelleme
Ruby 2.0 **
( alıntı yaptığım ) yaptığı çift uyarıyı (iki yıldız) tanıttı :
Ruby 2.0 anahtar kelime bağımsız değişkenlerini tanıttı ve **, * gibi davranıyor, ancak anahtar kelime bağımsız değişkenleri için. Anahtar / değer çiftleri içeren bir Hash döndürür.
... ve elbette bunu tanımlama yönteminde de kullanabilirsiniz :)
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}
Adlandırılmış öznitelikler örneği:
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}
Ben hepsi bir arada anahtar kelime argümanı, uyarısı ve çift uyarısı ile örnek oluşturmaya çalışıyordu:
define_method(:foo) do |variable1, variable2,*arg, i_will_not: 'work', **options, &block|
# ...
veya
define_method(:foo) do |variable1, variable2, i_will_not: 'work', *arg, **options, &block|
# ...
... ama bu işe yaramayacak, bir sınırlama var gibi görünüyor. Splat operatörü "kalan tüm argümanları yakalar" ve çift splat "kalan tüm anahtar kelime argümanlarını yakalar" olarak düşündüğünüzde, bunları karıştırmak beklenen mantığı bozacaktır. (Bu noktayı kanıtlamak için referansım yok doh!)
güncelleme Ağustos 2018:
Özet makale: https://blog.eq8.eu/til/metaprogramming-ruby-examples.html
a.foo 1
yerine foo 1
). Teşekkürler!
Kevin Conner'in cevabına ek olarak: blok argümanları yöntem argümanlarıyla aynı anlambilimi desteklemez. Varsayılan bağımsız değişkenleri tanımlayamaz veya bağımsız değişkenleri engelleyemezsiniz.
Bu sadece Ruby 1.9'da tam yöntem argüman semantiğini destekleyen yeni alternatif "stabby lambda" sözdizimi ile giderilmiştir.
Misal:
# 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' }
2.2 ile artık anahtar kelime argümanlarını kullanabilirsiniz: https://robots.thoughtbot.com/ruby-2-keyword-arguments
define_method(:method) do |refresh: false|
..........
end