11

Suppose I am working on an existing, reasonably large system. I have an object, myObject of class MyClass (for the example's sake, suppose I'm working in Java). myObject is a composition containing a Collection, say, a List and other objects which (I think) are irrelevant. It contains delegate methods which just serve to call upon the methods of the List it is composed of, in order to ensure the List it has is not exposed (sorry if I've got my terminology wrong).

Let's say that this List is a List<String> but, for some reason, the main access method is a mask method for class SomeOtherClass. If I wanted to insert a new value pair into my List, then I'd have an object of SomeOtherClass called someObject. I'd call myObject.insert(someObject) and inside the insert method there would be some magic that would retrieve a String to put into the List<String>.

Supposing now that I've only got a String value, and no SomeOtherClass object to insert. Assuming I can't modify the insert method because it would break everything in this system. Then should I overload the insert method? Or should I create a new object of SomeOtherClass every time I want to call insert?

I guess if I did overload it, it would look something like this...

public void insert(String s) {
    ...
}

public void insert(SomeOtherObject obj) {
    this.insert(obj.magicStringMethod());
}

(This example is a contrived puzzle based upon a similar (slightly more complex) situation regarding overloading that I encountered yesterday. I'll expand it if there's anything that was unclear)

Would this be an appropriate place to overload a method? If not, when should I overload a method?

blahman
  • 386

3 Answers3

9

You overload when you wish to support different types:

public overload void MyMethod(int value)
{ 
}

public overload void MyMethod(bool value)
{
}

public overload void MyMethod(string value)
{
}

or to support a progressive interface using different parameter lists:

public overload void MyOtherMethod()
{
    this.MyOtherMethod(DefaultValue);
}

public overload void MyOtherMethod(int value)
{
    this.MyOtherMethod(value, DefaultOtherValue);
}

public overload void MyOtherMethod(int value, bool otherValue)
{
    ...
}

You might even get a little crazy and support both different types AND a progressive interface, but you should bear in mind that you need to avoid creating variations in behaviour between overloaded methods. Each overloaded method should be functionally the same as the others in an overloaded group, otherwise it will be unclear as to how, when or why behaviour is being varied. If you want two functions to do something completely different, then you should name them accordingly.

S.Robins
  • 11,505
7

I would say that overloading is appropriate when both of the methods are semantically equivalent. To steal from dukeofgaming's examples:

These are overloaded appropriately:

public int sum(int a, int b){
    return a+b;
}

public double sum(double a, double b){
    return a+b;
}

These are not:

public int sum(int a, int b){
    return a+b;
}

public double sum(double a, double b){
    return a-b;
}

That is an extreme example (if you didn't catch it, the last method actually subtracts instead of adds), but the idea is that if you have multiple methods in a class with the same name they should behave consistently.

In your example, from the information given they appear to be equivalent (since one calls the other) and I would think it reasonable to overload them. It can't hurt to ask someone more senior in your team if you are unsure about whether the method should be added but if you did add it I would use the same name (i.e. I would overload it).

Gyan
  • 2,835
5

Essentially to have the parameters of the method dictate how the method will behave.

A quick example would be:

class Calc{
    //...
    public int sum(int a, int b){
        return a+b;
    }
    public double sum(double a, double b){
        return a+b;
    }
    //...
}

If you pass the method sum(a,b) a couple of integers it knows that it should call the first implementation, since the method call coincides with the method signature (i.e. double sum(double,double) will not work if you give the sum method two integers).

The signature of the call must match the available implementations, so trying to call sum(string, string) will not work unless you have this:

class Calc{
    //...
    public int sum(int a, int b){
        return a+b;
    }
    public double sum(double a, double b){
        return a+b;
    }
    public string sum(String a, String b){
        return "" + (Double.parseDouble(a) + Double.parseDouble(b));
    }
    //...
}

tl;dr: To have the class handle the correct method according to whatever parameters you give a method with the same name.

When inheriting, it is called overriding

A good example of this other scenario is when you want to alter the default behavior of a class by inheriting it, and particularly when you have something similar to the template method pattern, where you have each step of some algorithm implemented in a method.

Imagine that you have class Robot and a method called fireAtTarget(Target target)... which calls fireWeaponA(target); fireWeaponB(target); fireWeaponC(target); one after each other. You also want to have a collection called robot_army to which you can only add objects of the class Robot. Robot fires machine guns by default in its fireWeaponX() methods.

Then you want to have class LazorRobot and class MissileRobot, do you implement Robot all over again?, no, just have LazorRobot and MissileRobot inherit Robot, and overload each fireWeaponX() method to use lazorz or missiles and you will have the same behavior with different weapons, without having to reimplement the rest of the methods.

tl;dr: To have the method's behavior depend on the class without breaking the interface (robot_army only accepts Robot, but accepts by extension any classes that inherit Robot).

dukeofgaming
  • 14,023
  • 6
  • 52
  • 77