出于向后兼容的原因,是否有一种方法可以定义my
方法,因此以下两个调用是相同的?
my(1, A)
my(1, before: A)
其中before
是关键字参数。
我目前有
def my(n, klass)
puts "#{n} and #{klass}"
end
现在我需要能够调用my(1, before: A)
并获得相同的结果(即“ 1和A”)
还可以使用第二个关键字参数,即my
my(1, before: A, after: B)
方法
def my(n, before, after: nil)
puts "#{n} and #{before} but not #{after}"
end
答案 0 :(得分:4)
下面是MCVE及其用法示例。
def my(after = nil, **args)
after ||= args[:after]
before = args[:before]
puts "after = “#{after}” | before = “#{before}“"
end
my "A"
#⇒ after = “A” | before = ““
my after: "A"
#⇒ after = “A” | before = ““
my before: "B"
#⇒ after = “” | before = “B“
答案 1 :(得分:2)
您可以将方法定义为:
def my(n, klass = nil, before: nil)
p n: n, klass: klass, before: before
end
这允许您传递位置参数或关键字参数:
my(1, A)
#=> {:n=>1, :klass=>A, :before=>nil}
my(1, before: A)
#=> {:n=>1, :klass=>nil, :before=>A}
在该方法中,您可以将一个变量分配给另一个变量,即:
def my(n, klass = nil, before: nil)
klass ||= before
p n: n, klass: klass
end
my(1, A) #=> {:n=>1, :klass=>A}
my(1, before: A) #=> {:n=>1, :klass=>A}
或:
def my(n, klass = nil, before: nil)
before ||= klass
p n: n, before: before
end
my(1, A) #=> {:n=>1, :before=>A}
my(1, before: A) #=> {:n=>1, :before=>A}
后者可能更干净,另外还有一个after
关键字:
def my(n, klass = nil, before: nil, after: nil)
before ||= klass
p n: n, before: before, after: after
end
my(1, A, after: B) #=> {:n=>1, :before=>A, :after=>B}
my(1, before: A, after: B) #=> {:n=>1, :before=>A, :after=>B}
请注意,从技术上讲,您还可以同时通过klass
和before
或全部不通过:
def my(n, klass = nil, before: nil)
p n: n, klass: klass, before: before
end
my(1, A, before: A) #=> {:n=>1, :klass=>A, :before=>A}
my(1) #=> {:n=>1, :klass=>nil, :before=>nil}
在这种情况下,您可能想提出一个ArgumentError
。
答案 2 :(得分:0)
很遗憾,您的要求不是很清楚,但是我认为这应该可以满足您的要求:
def my(n, klass=nil, before: klass, after: nil)
local_variables.map {|var| next var.to_sym, binding.local_variable_get(var) }.to_h
end
my 1
#=> { n: 1, klass: nil, before: nil, after: nil }
my 1, 'A'
#=> { n: 1, klass: 'A', before: 'A', after: nil }
my 1, before: 'A'
#=> { n: 1, klass: nil, before: 'A', after: nil }
my 1, before: 'A', after: 'B'
#=> { n: 1, klass: nil, before: 'A', after: 'B' }
my 1, 'A', after: 'B'
#=> { n: 1, klass: 'A', before: 'A', after: 'B' }
my 1, 'A', before: 'B', after: 'C'
#=> { n: 1, klass: 'A', before: 'B', after: 'C' }
如果您想知道是否通过了klass
或before
,则必须使用旧的“将标志分配为副作用”:
def my(n, klass=(klass_not_passed = true; nil), before: (before_not_passed = true; klass), after: nil)
raise ArgumentError, "You may only pass one of `klass` or `before` but you passed `klass == #{klass.inspect}` and `before == #{before.inspect}`" unless klass_not_passed || before_not_passed
local_variables.map {|var| next var.to_sym, binding.local_variable_get(var) }.to_h
end
my 1
#=> { n: 1, klass: nil, before: nil, after: nil, klass_not_passed: true, before_not_passed: true }
my 1, 'A'
#=> { n: 1, klass: 'A', before: 'A', after: nil, klass_not_passed: nil, before_not_passed: true }
my 1, before: 'A'
#=> { n: 1, klass: nil, before: 'A', after: nil, klass_not_passed: true, before_not_passed: nil }
my 1, before: 'A', after: 'B'
#=> { n: 1, klass: nil, before: 'A', after: 'B', klass_not_passed: true, before_not_passed: nil }
my 1, 'A', after: 'B'
#=> { n: 1, klass: 'A', before: 'A', after: 'B', klass_not_passed: nil, before_not_passed: true }
my 1, 'A', before: 'B', after: 'C'
# ArgumentError: You may only pass one of `klass` or `before` but you passed `klass == "A"` and `before == "B"`
# from test.rb:36:in `my'