3

This is closely related to, but is not the same question as: Java - Method name collision in interface implementation

When there are two Java interfaces that share a method with almost the same signature like so:

import java.io.IOException;

interface ISomething1 {
    void doSomething();
}

interface ISomething2 {
    void doSomething() throws IOException;
}

class Impl implements ISomething1, ISomething2 {
  public void doSomething() {
    throw new IOException(); // this does not compile since ISomething1.doSomething does not declare a throws clause
  }

  public static void main(String args[]) throws IOException {
    Impl i = new Impl();
    i.doSomething();
  }
}

Why is it that Java enforces that only a single method implement both these interface methods even though technically they differ in signature?

Note also that in the example above, the implementation of Impl.doSomething needs to NOT throw an IOException as otherwise the compiler complains that ISomething1.doSomething must also declare that it throws IOException effectively making the throws clause in ISomething2.doSomething useless.

Am I missing something obvious here? Thanks in advance for responses.

Community
  • 1
  • 1
scorpiodawg
  • 5,612
  • 3
  • 42
  • 62
  • 3
    Just a question: could you come up with any real-life example why you would need this? Surely something is crooked in your design if this is needed... – Nanne Apr 12 '11 at 06:22

5 Answers5

2

When implementing a method in a child class, you can hide, or throw exceptions that "extends" the exception from the base class.

In your case:

public void doSomething() {
    throw new IOException(); // this does not compile since ISomething1.doSomething does not declare a throws clause
  }

the IOException is not a Runtime exception, and should be declared in the signature of the method. But this :

public void doSomething() throws IOException {
    throw new IOException(); // this does not compile since ISomething1.doSomething does not declare a throws clause
  }

doesn't obey rules described and is not valid due the

interface ISomething1 {
    void doSomething();
}

P.S. These aren't different signatures. If you want to throw a new exception and extend both interfaces - you may encapsulate the IOException in the next way:

throw new RuntimeException(new IOException());

UPDATE But this is dangerous because the user of the class(programmer) isn't enforced to catch this exception and this may broke end-user's experience.

StKiller
  • 7,631
  • 10
  • 43
  • 56
2

You might expect the compiler to know whether your client code intends to call void doSomething(); or void doSomething() throws IOException; based upon whether that client code handles the exception.

But the Java compiler is just not that clever.

(Of course, it would be impossible to infer which method the client wanted to call if the thrown exception was a RuntimeException - no matter how clever the compiler was).

The only things that make up the type of a method signature are the name and the parameters.

Synesso
  • 37,610
  • 35
  • 136
  • 207
  • Makes sense. As I mentioned in my previous comment above, this seems confusing from a language design perspective -- I wonder if it would have been better if Java provided disambiguation a la C#/.Net (via explicit interfaces) or simply disallowed this situation altogether via a compile error. – scorpiodawg Apr 13 '11 at 05:31
1

The method signature does not consist of the Exception thrown or the return value type. Therefore, to the compiler, both interfaces are declaring the same method.

euphoria83
  • 14,768
  • 17
  • 63
  • 73
0

By using generic names you have effectively tried to combine two unrelated methods. One method performs IO operations, the other does not appear to or must handle those errors it self. You have to decide which one it is and what the method should really be doing.

One hint you have confusion is that you have two interfaces, but you don't use them anywhere. i.e. you could delete them and your main() would compile just fine.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

First of all, I hope this is more of an academic question, than a problem that you are actually experiencing. If not, the answer is most likely you are making a mistake by implementing the two interfaces in a single class.

But to answer your question... Lets say there is some code that wants an object of type ISomething1 because it needs to doSomething with it. If your Impl class actually threw an exception the calling code would be utterly unprepared to handle the exception.

The opposite case is not true, therefore the compiler forces you to do it that way.

Jataro
  • 2,548
  • 1
  • 17
  • 17
  • Yes, this is kind of what I figured as well but this makes it confusing if such a situation existed. I think it would have been better if Java provided disambiguation a la C#/.Net (via explicit interfaces) or simply disallowed this situation period. – scorpiodawg Apr 13 '11 at 05:22