3

I have a class MyClass that implements the interface IResp.

public interface IResp {
    Response onResp(String a, String b)
            throws Throwable;
}
public class MyClass implements IResp {

    public onResp(String a, String b, String c) throws Throwable {
...
}

I need the additional String c in onResp method of MyClass

Now, I understand that I can achieve this either by adding unimplemented onResp(String a, String b) throws Throwable{...}, or by making MyClass an abstract class.

Since I'm new to Java, I'd like some advice on what's the better approach, please?

Note: I can make changes only to the class and cannot create or modify the interface

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
curiousCat
  • 157
  • 3
  • 11
  • 1
    Why not to use ... for arbitrary number of strings parameters in the interface definition? Take a look at the answer of this question https://stackoverflow.com/questions/3158730/what-do-3-dots-next-to-a-parameter-type-mean-in-java – Francisco Valle Sep 30 '21 at 07:23
  • 1
    If the users of `MyClass` only ever call it through `IResp`, then they will never see the variant with three parameters, they can only call the methods defined in `IResp`, which is `onResp(String a, String b)`, the three argument method is an overloaded method, not the same method. – Mark Rotteveel Sep 30 '21 at 08:03

3 Answers3

3

If you "implement" an interface method, and change the parameter signature (like adding a third String), this no longer is a valid implementation of the interface. You have to have a method like

public Response onResp(String a, String b) {
    // ...
}

in your MyClass.

I need the additional String c in onResp method of MyClass

The interface IResp most probably exists because there are callers of the onResp() method, and they will provide two Strings, not three. If your onResp() code really can't work without getting an additional piece of information (String c), you have a problem.

Your proposals both won't work (if I understand them correctly):

  • If you just add an empty onResp(String a, String b) method, then that method will be called from outside, do nothing and return.
  • If you declare MyClass to be abstract, then you won't be able to create instances of MyClass, and without an instance of this class, nothing will ever get called.

One (theoretical?) possibility is to change the interface method to use three instead of two parameters and to modify all callers of the interface to provide the expected information as a third parameter. But I guess the interface is fixed, and you're not free to do that.

If you can use the very same c value in all onResp() calls, you can provide the additional String c not with every onResp() call, but ahead of time, when you create the MyClass instance, doing new MyClass("abc"), assuming that "abc" is the appropriate value for c. Your class should look like this:

public class MyClass implements IResp {
    private String myConstantC;
    public MyClass(String c) {
        this.myConstantC = c;
    }
    privateResponse onResp(String a, String b, String c) {
        // your code
    }
    @Override
    public Response onResp(String a, String b) {
        return onResp(a, b, myConstantC);
    }
}

If you cannot live with a single constant c value, but have a chance to somehow find out the necessary c value for a given onResp(a, b) call, you can do something like

public class MyClass implements IResp {
    privateResponse onResp(String a, String b, String c) {
        // your code
    }
    private String findTheCValue(String a, String b) {
        // your way to find and return the correct c value
    }
    @Override
    public Response onResp(String a, String b) {
        String c = findTheCValue(a, b);
        return onResp(a, b, c);
    }
}
Ralf Kleberhoff
  • 6,990
  • 1
  • 13
  • 7
2

You have to implement method with two parameters if you implement interface IResp. But you can also define a second Method with 3 parameters. For example:

    public class MyClass implements IResp {

        public void onResp(String a, String b) throws Throwable {
            onResp(a, b, null);
        }


        public void onResp(String a, String b, String c) throws Throwable {
            // your logic
        }
    }
  • Thanks for your inputs @Wladimir. Do you mean that, on implementing the method with 2 parameters, I need to return onResp(a, b, null); like this?. public onResp(String a, String b) throws Throwable { return onResp(a, b, null); } – curiousCat Sep 30 '21 at 07:53
  • I mean, that onResp with 2 parameters in this implementation is simple onResp with 3 parameters where thirth parameter is null. And exactly if you have no void Method you have to return onResp(a, b, null); – Wladimir Diskowski Sep 30 '21 at 07:58
1

Did you mean implementing with an empty body? Implementing the method with an empty body could create problems. Let's assume someone created the method in the interface for a reason.

Say a function gets the interface as a parameter. Which method will they call on it? The two parameter version one.

void someWork( IResp resp ) 
{
 resp.onResp("a","b");
}

Now if the object actually passed in to resp is a MyClass with an empty implementation of the function, it does nothing. Is that what you want?

Making the class abstract would be the better choice than creating an empty implementation. It would mean that someone down the line will give the implementation that makes sends for the two parameter version.

If you implement the two parameter version with a sensible body in MyClass and add a three parameter version to MyClass, but you don't add it to the interface then functions such as f1 won't be able to use it.

The takeaway from this is that you will probably want both versions of onResp in the interface.

Gonen I
  • 5,576
  • 1
  • 29
  • 60
  • Thanks for your inputs @Gonen . Yes, I was asking about an empty implementation. But, yes I definitely don't want to complicate when it does nothing. although, I agree that it's better to have both implementations in the interface, it's a shame that I cannot modify the interface itself. Hence my concern. – curiousCat Sep 30 '21 at 07:42
  • @curiousCat Then another option is to create another interface with just the 3 parameter version, and not let MyClass implement the two version. You could have the new interface extend the old one, but then you would again need to decide on an implementation for the two version one. – Gonen I Sep 30 '21 at 07:50
  • I understand that would be a better approach. Sorry, I should have mentioned this earlier. But, unfortunately, I can only make changes to the class. I cannot modify or create a new interface. – curiousCat Sep 30 '21 at 07:56