など、より具体的名称、あなたがあなたの目標を達成するために、いくつかのメタプログラミングを試みることができるとオーバーロードメソッドの名前を変更することができます。
は、次のコードを参照してください:
class OverloadError < ArgumentError; end
class Class
=begin rdoc
=end
def define_overload_method(methodname, *methods)
methods.each{ | proc |
define_method("#{methodname}_#{proc.arity}".to_sym, &proc)
}
define_method(methodname){|*x|
if respond_to?("#{methodname}_#{x.size}")
send "#{methodname}_#{x.size}", *x
else
raise OverloadError, "#{methodname} not defined for #{x.size} parameters"
end
}
end
end
class X
define_overload_method :ometh,
Proc.new{ "Called me with no parameter" },
Proc.new{ |p1| "Called me with one parameter (#{p1.inspect})" },
Proc.new{ |p1,p2| "Called me with two parameter (#{p1.inspect}, #{p2.inspect})" }
end
x = X.new
p '----------'
p x.ometh()
p x.ometh(1)
p x.ometh(1,2)
p x.ometh(1,2,3) #OverloadError
あなたはdefine_overload_method
であなたのオーバーロードされたメソッドを定義することができます。パラメータは、メソッド名とプロシージャのリストです。メソッドが作成され、対応するメソッドが呼び出されます。どのメソッドがパラメータの数によって決まるか(タイプしない!)
代替構文は次のようになります。
class OverloadError < ArgumentError; end
class Class
def def_overload(methodname)
define_method(methodname){|*x|
if respond_to?("#{methodname}_#{x.size}")
send "#{methodname}_#{x.size}", *x
else
raise OverloadError, "#{methodname} not defined for #{x.size} parameters"
end
}
end
def overload_method(methodname, proc)
define_method("#{methodname}_#{proc.arity}".to_sym, &proc)
end
end
class X
def_overload :ometh
overload_method :ometh, Proc.new{ "Called me with no parameter" }
overload_method :ometh, Proc.new{ |p1| "Called me with one parameter (#{p1.inspect})" }
overload_method :ometh, Proc.new{ |p1,p2| "Called me with two parameter (#{p1.inspect}, #{p2.inspect})" }
end
def_overload
はoverload_method
は1「過負荷法」を定義して、あなたのオーバーロードされたメソッドのためのフレームを定義します。
しかし、すでにmentioned by Holger:
あなたはRubyのやり方に適応しようとする必要があります。 Rubyに過負荷がない理由があります。メソッドはただ一つのことを行うべきであり、異なる引数のためにまったく異なることを魔法のように決めるのではありません。代わりにダックタイピングを利用しようとすると、疑わしい場合は意味のある名前で別のメソッドを使用してください。
私はタイプ敏感オーバーロードとバージョンを実装する方法に興味がありました。ここにある:あなたが
p x.ometh(1)
p x.ometh('a')
でそれを呼び出すと
class OverloadError < ArgumentError; end
class Class
def def_overload(methodname)
define_method(methodname){|*x|
methname = "xxx"
methname = "#{methodname}_#{x.size}#{x.map{|p| p.class.to_s}.join('_')}"
if respond_to?(methname)
send methname, *x
elsif respond_to?("#{methodname}_#{x.size}")
send "#{methodname}_#{x.size}", *x
else
raise OverloadError, "#{methodname} not defined for #{x.size} parameters"
end
}
end
def overload_method(methodname, *args, &proc)
types = []
args.each{|arg| types << arg.to_s}
define_method("#{methodname}_#{proc.arity}#{types.join('_')}".to_sym, &proc)
end
end
class X
def_overload :ometh
overload_method(:ometh){ "Called me with no parameter" }
overload_method(:ometh, String){ |p1| "Called me with one string parameter (#{p1.inspect})" }
overload_method(:ometh){ |p1| "Called me with one parameter (#{p1.inspect})" }
overload_method(:ometh){ |p1,p2| "Called me with two parameter (#{p1.inspect}, #{p2.inspect})" }
end
あなたは
"Called me with one parameter (1)"
"Called me with one string parameter (\"a\")"
私は長さオプションが好きではありません... argsはnilとして渡すことができます。少なくともこれは読みにくいです。 – Arth
あなたはRubyの方法に適応しようとする必要があります。 Rubyに過負荷がない理由があります。メソッドはただ一つのことを行うべきであり、異なる引数のためにまったく異なることを魔法のように決めるのではありません。代わりに、[Duck Typing](http://en.wikipedia.org/wiki/Duck_typing)を利用しようとしてください。疑わしい場合は、意味のある名前でさまざまな方法を使用してください。 –
さらにお問い合わせ:いくつかのパラメータでオーバーロードする(例のように)か、パラメータのタイプを使用するか?例えば、メソッドは 'a(1)'と 'a( 'x')'を同じ呼び出しか、呼び出しを別の方法で実行していますか? – knut