Tuesday, May 8, 2012

Method Overloading

The Realbasic language supports the ability for methods to have different sets of parameters. One version of a method might take two integers, and another an integer and a string. This is called "method overloading" and the act of determining which overload to invoke is called "overload resolution". 

When you call an overloaded method, the compiler has to figure out which one you mean. It first determines what overloads are valid to call with the given parameters. Then, it takes this list of valid overloads and counts the conversions required to invoke each one. Whichever overload requires the least amount of conversions is the winner and ends up being called. If there is no winner (i.e. there are multiple methods with the same number of conversions), the call is ambiguous and the compiler throws an error.

Now, applying this knowledge to a real world case: consider ListBox.AddRow, which has two overloads:
Sub AddRow(items() as String)
Sub AddRow(ParamArray items() as String)

and the following code:
dim v as Variant = "My string"
listBox1.AddRow( v )

When you pass in a variant, the compiler first sees that both overloads are valid (since variants can convert to arrays or strings). Next, it looks at the number of conversions required and discovers that both of them require one conversion (Variant -> String() or Variant -> String). Since the compiler can't tell which one you want, it gives back an error:

"There are several items with this name and it is not clear which one the call refers to"

In this case, the problem could have been avoided by not using variants (or saying 'v.StringValue', which makes your intention explicit). The issue with variants is that they can implicitly convert themselves to any type and often have unintended side effects. They also effectively bypass some of the compiler's type checking, delaying errors until you run your program.


Jason said...

It's worth also noting that methods cannot be overloaded based on the return; only the parameters may be used. So the example Joe provided works because the parameters are different. On the other hand, consider the following:

Function Foo() As Bar
Function Foo() As MoreBar

Intuitively, the two are different. But this won't work. While they are distinct, the compiler is unable to determine which is intended when used. To show why, consider the function being called:

Call Foo()

If the value isn't being returned, how is the compiler to know which function was intended? And thus it breaks. Moral of the story: Only use parameters to overload methods.

Hope this helps. :)

Joe Ranieri said...

There's actually one case where you can overload on return type: Operator_Convert.

anic297 said...

First, I thought it was a good explanation of why a different return type was not allowed for method overloading (I'm asking this myself since a long time ago).

But, the example doesn't seem valid to me: when using “Call Foo()”, the compiler could as well do exactly the same as with the parameters example and show “There are several items with this name and it is not clear which one the call refers to". Still, unless with “call”, methods should be overloaded just fine with a different return value.