Method Overloading. Can You Overuse It

Method Overloading. Can you overuse it?

Yes, overloading can easily be overused.

I've found that the key to working out whether an overload is warranted or not is to consider the audience - not the compiler, but the maintenance programmer who will be coming along in weeks/months/years and has to understand what the code is trying to achieve.

A simple method name like GetProducts() is clear and understandable, but it does leave a lot unsaid.

In many cases, if the parameter passed to GetProducts() are well named, the maintenance guy will be able to work out what the overload does - but that's relying on good naming discipline at the point of use, which you can't enforce. What you can enforce is the name of the method they're calling.

The guideline that I follow is to only overload methods if they are interchangable - if they do the same thing. That way, I don't mind which version the consumer of my class invokes, as they're equivalent.

To illustrate, I'd happily use overloads for a DeleteFile() method:

void DeleteFile(string filePath);
void DeleteFile(FileInfo file);
void DeleteFile(DirectoryInfo directory, string fileName);

However, for your examples, I'd use separate names:

public IList<Product> GetProductById(int productId) {...}
public IList<Product> GetProductByCategory(Category category) {...}
public IList<Product> GetProductByName(string Name ) {...}

Having the full names makes the code more explicit for the maintenance guy (who might well be me). It avoids issues with having signature collisions:

// No collisions, even though both methods take int parameters
public IList<Employee> GetEmployeesBySupervisor(int supervisorId);
public IList<Employee> GetEmployeesByDepartment(int departmentId);

There is also the opportunity to introduce overloading for each purpose:

// Examples for GetEmployees

public IList<Employee> GetEmployeesBySupervisor(int supervisorId);
public IList<Employee> GetEmployeesBySupervisor(Supervisor supervisor);
public IList<Employee> GetEmployeesBySupervisor(Person supervisor);

public IList<Employee> GetEmployeesByDepartment(int departmentId);
public IList<Employee> GetEmployeesByDepartment(Department department);

// Examples for GetProduct

public IList<Product> GetProductById(int productId) {...}
public IList<Product> GetProductById(params int[] productId) {...}

public IList<Product> GetProductByCategory(Category category) {...}
public IList<Product> GetProductByCategory(IEnumerable<Category> category) {...}
public IList<Product> GetProductByCategory(params Category[] category) {...}

Code is read a lot more than it is written - even if you never come back to the code after the initial check in to source control, you're still going to be reading that line of code a couple of dozen times while you write the code that follows.

Lastly, unless you're writing throwaway code, you need to allow for other people calling your code from other languages. It seems that most business systems end up staying in production well past their use by date. It may be that the code that consumes your class in 2016 ends up being written in VB.NET, C# 6.0, F# or something completely new that's not been invented yet. It may be that the language doesn't support overloads.

How to overload method with different typed Lists?

You have to give them different names, because the methods above have the same erasure.

Information about concrete generic types is not stored in the runtime, so if you keep the signatures above JVM will not be able to realise what method should be called in the runtime if you pass any list of objects as an argument.

For more information about erasure, please see https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

Why is method overloading not defined for different return types?

You can of course have overloading for methods which differ by return type, just not for methods which differ only by return type. For example, this is fine:

def foo(s: String) : String = s + "Hello"
def foo(i: Int) : Int = i + 1

That aside, the answer to your question is evidently that it was a design decision: the return type is part of the method signature as anyone who has experienced an AbstractMethodError can tell you.

Consider however how allowing such overloading might work in tandem with sub-typing:

class A {
def foo: Int = 1
}
val a: A = //...lookup an A
val b = a.foo

This is perfectly valid code of course and javac would uniquely resolve the method call. But what if I subclass A as follows:

class B extends A {
def foo: String = "Hello"
}

This causes the original code's resolution of which method is being called to be broken. What should b be? I have logically broken some existing code by subtyping some existing class, even though I have not changed either that code or that class.

Is a bad practice to Return different types when overloading a method?

I would recommend calling the second one GetAll.

Right now, it isn't obvious that the second method returns a collection.

You should strive to ensure that your classes are as obvious as possible and do not contain any unexpected surprises.

Method Overloading with Types C#

What you're trying to do is possible like this:

class TestClass<T>
{
public string GetName<T>()
{
Type typeOfT = typeof(T);
if(typeOfT == typeof(string))
{
//do string stuff
}
}
}

While this is possible, you're kind of defeating the purpose of generics. The point of generics is when the type doesn't matter, so I don't think generics is appropriate in this case.

When should we use method overloading vs method with different naming

Overloading for sure.

Okay, so it's not "obvious" which function gets called (arguable)...so what? You don't care that it can take different types of parameters, it just needs to do its thing. If you have different behavior based on different overloads, you've abused overloads, not pointed out a flaw in them.

An example of abusing overloads:

// good:
struct has_properties
{
void property1(float); // set property1, which happens to be a float
void property2(int); // set property2, which happens to be an int
};

// bad:
struct has_properties
{
void property(float); // set property1, abusing that it's a float
void property(int); // set property2, abusing that it's an int
};

Hopefully you see the problem here. If two functions have the same name, they should do the same thing.

Even better, if you're merely trying to allow the possibility for operating on different types, just use a template. (This arguably is a form of overloading.)

C#, How to make overload methods share summary tag

Even though the method names are same, but they can have different implementation and can do different things. Hence you need to provide separate summary for each of them.

Webservice method overloading

Operation Overloading is a concept available in Object Oriented programming languages. However, WebServices are not limited to OO platforms. They are message oriented, where the message can be constructed/deconstructed in any platform of your choice. Since all platforms do not provide operation overloading, and since web-services are meant for integration across platforms, it is illegal for web-services to support operation overloading.

Now, the reality is slightly different. I can see several articles online where developers have done such stuff. OASIS themselves had some confusion it seems, but they finally ruled against operation overloading (see section-3.6) .



Related Topics



Leave a reply



Submit