views:

69

answers:

8

For example

public interface X{
    public void foo(X i);
}

public class Y implements X{//error: doesn't implement foo(X i)...
    public void foo(Y i){
        fooBar(foo);
    }
    ....
}

Why can't I do that? And how can I change it so this is possible? What can I do to declare foo in X with a parameter, and then be able to use Y as the parameter type in Y?

A: 

Because Java is designed this way.

klez
Thanks. I'd upvote you, but I'd hate to change that rep of yours.
Cam
Yes... Gotta keep that rep there.
chris
I have to take a snapshot.
klez
damnit. Alright you should probably go make a question and accept an answer.
Cam
It ought be a stupid question, if I get upvote for that I'm down
klez
+4  A: 

By changing the type of the input parameter in class Y, you have changed the signature of the method which means the compiler sees it as a completely different method.

A Java interface is like a contract. Anything implementing it must implement the exact methods it defines. By using a different method signature you are not really implementing the defined method and so you are breaking that contract.

Donal Boyle
+4  A: 

Additionally to what Don Boyle said, you can't change it without hinting the compiler of the intention. You do this by introducing Generics to the interface, like so:

public interface X<T> {
    public void foo(T i);
}

public class Y implements X<Y> {
    public void foo(Y i){
        fooBar(foo);
    }
}
Esko
Ah - there we go. That's what I was looking for. I tried something like that but it didn't work. Good stuff.
Cam
+1  A: 

Try something like

interface X<T extends X> {
    public void foo(T a);
}

class Y implements X<Y> {
    public void foo(Y a);
}
Steven Schlansker
A: 

You can do that, as long as you also implement a method with the signature public void foo(X i). In Java a method (its signature) is uniquely defined by the combination of its identifier and its parameters. Therefore, you have declared a completely different method in the implementation, and have not implemented the method declared in the interface.

The design I (and I think most other Java programmers) would expect to see is this:

public interface X{
    public void foo(X i);
}

public class Y implements X{
    public void foo(X i){
        fooBar(foo);
    }
    ....
}

It's perfectly okay - in fact, I'd say it's better - to reference the interface in an implementing class.

Matt Ball
A: 

Suppose you had done as you want, and suppose Java allowed it. And let's say another class - call it Z - also implements X. Because Z implements X, and because of the definition of X, you must be able to call X.foo(z) for any Z z. But Y, which is an X, doesn't know what to do if you pass a Z to its foo(). That's why.

Carl Manaster
A: 

By implementing the interface X, you promise that you implement all methods on this interface, which means that your foo method can take an arbitrary X. Now if you would just accept Ys as the parameter to your foo method, you would not fully implement the interface as all other classes implementing X were not valid parameters for foo.

FRotthowe
A: 

Because Interface specifies common behavior for all implementing classes. Let's say you'd have some other classes all implementing X you would expect that if you have object of class X you can call foo with parameter that is of class X (which can be any of it's subclasses or implementations) so let's say you'd have code like this:

class Z implements X {
  ...
}

Z z = new Z();
X x = new Y();
x.foo(z);

Which would be false since with your code foo would only accept arguments of class Y

kane77