#16 Method overloading

brian Wed 21 Dec 2005

I've been thinking a lot about method overloading, and in short I think Fan should not support method overloading by parameter type. The basic reason is that methods purely identified by name are vastly simpler to work with - especially when we are trying to do dynamic dispatch at runtime. It also makes mixins and type augmentation at runtime way simpler too. Without this simplification I think it would basically be impossible to build a dynamic dispatch system that performed acceptably on the JVM and CLR. With it is dynamic dispatch is a simple string based hashmap lookup.

Method overloading is practically required in Java (and C#) for a couple reasons, which I believe we solve in Fan:

  • Supporting low level variations for all the primitives. I think in many respects this problem goes away because we wrap these calls (for example it's not Math.abs, but rather Int.abs/Real.abs). Supporting extended methods (adding a method to existing class) makes this even easier.
  • Defaulting arguments - it is extremely common to create methods that just call another method with some default arguments. But I definitely want to support default arg values in Fan (implementation is a bit tricky, but I have some ideas).
  • Constructors are probably where it will hurt the most, but actually I am not sure we couldn't leave them overloaded.

The harder part to figure out what do to when you are calling methods against native libraries which do make sure of method overloading. We could support only at the compiler level, but it still gets ugly when running in script mode or using the Fan reflection APIs.

So far the only place where we really have used method overloading is in List slice:

List
{
  Obj slice(Int)
  Obj slice(Range)
}

But I think the fix for that is to change operator overloading to these rules:

a[b]     ->  a.get(b)
             a.slice(b)     // if b is Range
a[b] = c ->  a.set(b, c)
             a.splice(b, c) // if b is Range

It's not quite as elegant, but probably better method names for the common case.

andy Wed 21 Dec 2005

I'm on the fence on this one - I'll have to think about it - but it may be OK, because you're right, since we don't have primitives, the only other time I would overload via params is when the methods could easily have different names, or in the case where we have default values.

I'm not sure if Ruby does this, but I have seen patterns in Rails where the method list seems to be hashmap, which seems like a really cool idea:

// Label ctor, with defaults for all values
Label(text = "", color = "black", font = "11px Tahoma")
{
  this.text  = text;
  this.color = color;
  this.font  = font;
}

// These are all valid.  I don't need a hashmap in
// the first two since they are defined in order.
// However, I use one in 'c' because I want to skip
// color.
a := new Label("Text")
b := new Label("Text", "red")
c := new Label([text:"Text", font:"bold 18px Arial"])

This way I don't have to define a gazillion ctors for all the common use cases - you always have a "catch-all ctor".

brian Thu 22 Dec 2005

I think your constructor case is handled by C# 3.0 style object initializers like I discussed the other day (something we want to make defining config data in Fan easy):

Point p = new Point { X = 0, Y = 1 };

Although using that model for all methods does have some advantages - but haven't really been thinking of that as a feature.

Login or Signup to reply.