Tôi muốn chuyển (các) đối số cho một phương thức được xác định bằng cách sử dụng notify_method, tôi sẽ làm điều đó như thế nào?
Tôi muốn chuyển (các) đối số cho một phương thức được xác định bằng cách sử dụng notify_method, tôi sẽ làm điều đó như thế nào?
Câu trả lời:
Khối mà bạn chuyển đến định nghĩa_method có thể bao gồm một số tham số. Đó là cách phương thức được xác định của bạn chấp nhận đối số. Khi bạn xác định một phương thức, bạn thực sự chỉ cần đặt biệt danh cho khối và giữ một tham chiếu đến nó trong lớp. Các tham số đi kèm với khối. Vì thế:
define_method(:say_hi) { |other| puts "Hi, " + other }
... và nếu bạn muốn các tham số tùy chọn
class Bar
define_method(:foo) do |arg=nil|
arg
end
end
a = Bar.new
a.foo
#=> nil
a.foo 1
# => 1
... nhiều tranh luận như bạn muốn
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']
...sự kết hợp của
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]
... Tất cả bọn họ
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
Cập nhật
Ruby 2.0 đã giới thiệu splat đôi **
(hai sao) mà ( tôi trích dẫn ) hiện:
Ruby 2.0 đã giới thiệu các đối số từ khóa và ** hoạt động như *, nhưng đối với các đối số từ khóa. Nó trả về một Hash với các cặp khóa / giá trị.
... Và tất nhiên bạn cũng có thể sử dụng nó trong phương thức xác định :)
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}
Ví dụ thuộc tính được đặt tên:
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}
Tôi đã cố gắng tạo ví dụ với đối số từ khóa, splat và double splat tất cả trong một:
define_method(:foo) do |variable1, variable2,*arg, i_will_not: 'work', **options, &block|
# ...
hoặc là
define_method(:foo) do |variable1, variable2, i_will_not: 'work', *arg, **options, &block|
# ...
... nhưng điều này sẽ không hoạt động, có vẻ như có một hạn chế. Khi bạn nghĩ về nó có ý nghĩa vì toán tử splat là "nắm bắt tất cả các đối số còn lại" và splat kép là "nắm bắt tất cả các đối số từ khóa còn lại", do đó trộn chúng sẽ phá vỡ logic dự kiến. (Tôi không có bất kỳ tài liệu tham khảo nào để chứng minh điểm này doh!)
cập nhật 2018 tháng 8:
Tóm tắt bài viết: https://blog.eq8.eu/til/metaprogramming-ruby-examples.html
a.foo 1
thay vì foo 1
). Cảm ơn!
Ngoài câu trả lời của Kevin Conner: các đối số khối không hỗ trợ cùng một ngữ nghĩa như các đối số phương thức. Bạn không thể xác định đối số mặc định hoặc đối số khối.
Điều này chỉ được sửa trong Ruby 1.9 với cú pháp "stabby lambda" thay thế mới hỗ trợ ngữ nghĩa đối số phương thức đầy đủ.
Thí dụ:
# 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' }
Với 2.2, giờ đây bạn có thể sử dụng các đối số từ khóa: https : //robots. Dùtbot.com / ruby-2- keyword -argument
define_method(:method) do |refresh: false|
..........
end