In C++ it's possible to have function overloading... ie
void foo(int a) and void foo(rational a)
Do I have to resort to
def foo(a)
case a
when Fixnum ...
when Rational ...
end
end
or is there any other way to do this?
Essentially it's what you've written. However, you'll find that in more
cases than you expect you don't actually do it. As long as the objects
passed in respond to the same methods, you can just invoke them without
caring what the class is; there is no need for them to be inherited from
some common superclass as would be the case in C++.
As an example:
def foo(logger)
logger << "hello world\n"
end
This works whether logger is a File, a String, or an Array (even though
their common ancestors are Object and Kernel, which don't have a <<
operator). There's no need to write
def foo(logger)
case logger
when File ...
when String ...
when Array ...
end
end
It doesn't work if logger is a Fixnum, but then, it doesn't make sense to
append a log string to a Fixnum anyway.
Have a look through Ruby's built-in library. For example, in 'expect.rb'
you'll see several cases where a function can be called either with a hash
or a string as an argument, and it behaves differently in those cases.
Actually, you're often more interested in what methods an object responds
to, rather than its class. In the logger example you're more likely to have
logger.flush if logger.respond_to?
flush)
rather than
case logger
when File, IO
logger.flush
end
You're basically assuming a convention that an IO-like object has methods
"<<" to append and "flush" to flush (if it can be flushed). Such conventions
seem to work well in practice. If you came across an object which didn't,
you could add a "<<" method to that object or to its class to do what you
want, or make a wrapper object which normalises the method call interface.
Exception handling is another way to avoid explicit tests for class:
begin
logger.flush
rescue NoMethodError
end
Regards,
Brian.