Reputation: 955
I have seen similar questions to this one. However, I could not find an exact answer to this. I want to know the best approach of following ones based on circumstances. Please explain advantages and disadvantages of case 1 and case 2?.
Case 1 :
public class Test {
public void method1(String s) {
System.out.println("String s");
}
public void method1(String s, String a) {
System.out.println("String s" + "String a");
}
}
Case 2:
I wrote the code in following way. It is a simple logic, I wanted to demonstrate only the implementation
public class Test {
public void method1(String s) {
new Test().methodImpl(s,null);
}
public void method1(String s, String a) {
new Test().methodImpl(s,a);
}
public void methodImpl(String x , String y){
if(y!=null){
System.out.println("String s" + "String a");
}else if(y==null){
System.out.println("String s");
}
}
}
Upvotes: 4
Views: 210
Reputation: 9192
I like to do it a slightly different way which I think allows for more flexibility. It can eliminate the need for a lot of different overloading. The example method below eliminates the need of all the methods contained within your Test Class and allows for more flexibility, for example:
It can optionally accept NONE to an unlimited number of string arguments:
new Test().method();
or
new Test().method("This is a String.");
or
new Test().method("This ", "is", " a", " string", " that", " will ", "be", " displayed.");
It can also accept a Single Dimensional (1D) String Array as a single argument.
String[] stringArray = {This ", "is", " a", " string", " that", " will ", "be", " displayed."};
new Test().method(stringArray);
If you look at the Test Class below you can see that only one method is required:
public class Test {
public void method(String... args) {
if (args.length > 0) {
// Build the string from the supplied string arguments...
StringBuilder sb = new StringBuilder();
for (String strg : args) {
// A 'Ternary Operator' is used below in case an argument is null.
sb.append(strg == null ? "" : strg);
}
System.out.println(sb.toString()); // Display built string in console.
}
}
What can you do if the parameter for this method was: Object... args
?
I sometimes use this technique for class Constructors as well, for example:
public class Test {
// Class Constructor
public Test (String... args) {
method(args);
}
public void method(String... args) {
if (args.length > 0) {
// Build the string from the supplied string arguments...
StringBuilder sb = new StringBuilder();
for (String strg : args) {
// A 'Ternary Operator' is used below in case an argument is null.
sb.append(strg == null ? "" : strg);
}
System.out.println(sb.toString()); // Display built string in console.
}
}
And to use it:
String[] stringArray = {"This ", "is", " a ", "string", " that", " will ", "be", " displayed."};
new Test(stringArray); // You will notice a warning but it works.
or
new Test(); // You will notice a warning but it works.
or
new Test("This is one Argument"); // You will notice a warning but it works.
or
new Test("This ", "is", " many ", "Arguments."); // You will notice a warning but it works.
or
Test test = new Test("This ", "is", " many ", "Arguments.");
or
Test test = new Test();
test.method("This is one Argument");
or
String[] args = {"This ", "is", " many ", "Arguments."};
Test test = new Test(args);
test.method(args);
The last example will display: This is many Arguments.
twice in console. Can you see why?
Upvotes: 1
Reputation: 74605
These aren't different forms of overloading per se; there's only one form of overloading in Java (you could argue that eh C#'s optional parameters achieve the intent of overloading) which is to provide multiple methods with different signatures.
Your examples are a little too simplistic to be useful for explaining because they don't really save any code. Case 1 duplicates code meaning it becomes a maintenance nightmare, and case 2 makes the method list messy and the implementation messy because it just becomes a massive if statement again with duplicated code because you've dumped entire method bodies into an if - it turns 4 lines of code into 7 and it didn't solve anything that case 1 presented as a problem; if you find a bug you still have to change it in two places.
Consider a more realistic example, and instead let's have a method that does the work and then other overloads that just call it (it might not be a perfect example but it sprang to mind as a common operation that is fairly self explanatory):
public SendEmail(string to, string message){
SendEmail(to, message, null);
}
public SendEmail(string to, string message, Credentials c){
MailClient mc = new MailClient();
if(c == null){
if(!to.endsWith("@local"))
// throw exception; non local email delivery requires a credential
} else {
mc.Credentials = c;
}
mc.Send(to, message);
}
Here we have one implementation, we do some if statements that partially change the behaviour, rather than duplicating an entire method body inside the if / else blocks, without repeated code and we have the simpler overload call the more extensive one
A lot of things in coding are personal choice but this is how I would expect to see "overloading for the sake of providing simplified versions of a complex method call". By contrast I don't find either of your cases to have any particular advantages over each other that aren't cancelled out by their disadvantages; case 1 is neater but duplicates code, case 2 is messier than necessary, and duplicates code, but does partly aim for the "simple signatures calling complex signatures" route
Upvotes: 2
Reputation: 319
In case 1 you need to write duplicate logic code in each method and in case 2 you have written extra method that we can reduce as per below code
public class Test {
public void method1(String s) {
method1(s,null);
}
public void method1(String s, String a) {
if(a!=null){
System.out.println("String s" + "String a");
}else{
System.out.println("String s");
}
}
}
Upvotes: 1