T
Trans
Have a need to create method overloading, so I put together an
implementation. Curious what other think of it; how to improve it; or
do it a better way.
Thanks,
T.
# ---- overload.rb
class Module
def method_overloads
@method_overloads ||= {}
end
def overload( name, *signiture, &block )
name = name.to_sym
if method_overloads.key?( name )
method_overloads[name][signiture] = block
else
method_overloads[name] = {}
method_overloads[name][signiture] = block
if method_defined?( name )
#method_overloads[name][nil] = instance_method( name ) #true
alias_method( "#{name}Generic", name )
has_generic = true
else
has_generic = false
end
define_method( name ) do |*args|
ovr = self.class.method_overloads[:"#{name}"]
sig = args.collect{ |a| a.class }
hit = nil
faces = ovr.keys.sort { |a,b| b.size <=> a.size }
faces.each do |cmp|
next unless cmp.size == sig.size
cmp.size.times { |i|
next unless cmp < sig
}
hit = cmp
end
if hit
ovr[hit].call(*args)
else
if has_generic #ovr[nil]
send( "#{name}Generic", *args )
#ovr[nil].bind(self).call(*args)
else
raise NoMethodError
end
end
end
end
end
end
# _____ _
# |_ _|__ ___| |_
# | |/ _ \/ __| __|
# | | __/\__ \ |_
# |_|\___||___/\__|
#
class X
def x
"hello"
end
overload :x, Integer do |i|
i
end
overload :x, String, String do |s1, s2|
[s1, s2]
end
end
x = X.new
p x.x
p x.x(1)
p x.x("a","b")
implementation. Curious what other think of it; how to improve it; or
do it a better way.
Thanks,
T.
# ---- overload.rb
class Module
def method_overloads
@method_overloads ||= {}
end
def overload( name, *signiture, &block )
name = name.to_sym
if method_overloads.key?( name )
method_overloads[name][signiture] = block
else
method_overloads[name] = {}
method_overloads[name][signiture] = block
if method_defined?( name )
#method_overloads[name][nil] = instance_method( name ) #true
alias_method( "#{name}Generic", name )
has_generic = true
else
has_generic = false
end
define_method( name ) do |*args|
ovr = self.class.method_overloads[:"#{name}"]
sig = args.collect{ |a| a.class }
hit = nil
faces = ovr.keys.sort { |a,b| b.size <=> a.size }
faces.each do |cmp|
next unless cmp.size == sig.size
cmp.size.times { |i|
next unless cmp < sig
}
hit = cmp
end
if hit
ovr[hit].call(*args)
else
if has_generic #ovr[nil]
send( "#{name}Generic", *args )
#ovr[nil].bind(self).call(*args)
else
raise NoMethodError
end
end
end
end
end
end
# _____ _
# |_ _|__ ___| |_
# | |/ _ \/ __| __|
# | | __/\__ \ |_
# |_|\___||___/\__|
#
class X
def x
"hello"
end
overload :x, Integer do |i|
i
end
overload :x, String, String do |s1, s2|
[s1, s2]
end
end
x = X.new
p x.x
p x.x(1)
p x.x("a","b")