my dog learned polymorphism*
The moose likes Java in General and the fly likes narrowing of type and interfaces Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "narrowing of type and interfaces" Watch "narrowing of type and interfaces" New topic
Author

narrowing of type and interfaces

Joe Khan
Greenhorn

Joined: Aug 27, 2004
Posts: 15
Consider the following situation:
----------------
interface A{
void a();
}
----------------
interface B{
void b(A av);
}
----------------
class myA implements A
{
public void a() {

}
}
-----------------------

class myB implements B{

public void b(myA av) {


}
------------------
The last class doesn't complie. It gives me this error:
myB is not abstract and does not override abstract method b(A) in B


The problem is myA is of type A since it's implementing interface A, so I guess there shouldn't be the error theoretically. or is it a bug with JDK compiler? I'm using JDK 1.6.0_02.
[ December 15, 2007: Message edited by: Joe Khan ]

All things are difficult before they are easy...
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
The compiler is pretty picky when matching signatures. Your myA class is indeed an A, but it's a special kind of A. Other users of myB would see implements B and expect to call your method with any implementation of A. The compiler requires you to accept any kind of A, not just myA.

Experiment with making the myA method use A or a supertype of A, say Object. Do any of those work better? Do they make sense?


A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14074
    
  16

This is not a compiler error, and it's correct that you get an error message here. If a non-abstract class implements an interface, then it must provide implementations for all methods in the interface with the correct method signature (method name and argument types). You cannot implement an interface and change the method signature by changing the type of the arguments. I'll try to explain why.

Suppose you declare a variable 'obj' like this:

B obj = new myB();

And now you want to call the method 'b' on 'obj'. Since the type of 'obj' is B, the compiler will check if the arguments you pass to method 'b' are of the type as specified in interface B. According to interface B, you can pass anything that implements A to the method. But your class myB has more strict requirements; it requires that the argument is an instance of myA or of a subclass of myA.

The compiler can't be sure at compile time that 'obj' refers to a myB, and so it cannot check the more strict requirement.

You might now ask "Why can't the compiler check that 'obj' refers to a myB? The compiler knows that if I do B obj = new myB();, doesn't it?".

In this case the compiler maybe could have known it, but that's not so in the more general case. You could for example have instantiated a class via reflection:

Class cls = new Class("myB");
B obj = cls.newInstance();


If you do that, there's no way the compiler could have known at compile-time to what kind of object 'obj' refers at runtime.
[ December 15, 2007: Message edited by: Jesper Young ]

Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 7 API documentation
Scala Notes - My blog about Scala
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
In short, being able to do that would violate Liskov's Substitution Principle: http://en.wikipedia.org/wiki/Liskov_substitution_principle


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Joe Khan
Greenhorn

Joined: Aug 27, 2004
Posts: 15
Hey thanks you guys for responses.
According to Ilja
(1)A is not substitutable by myA(A is a super type not a sub type of myA).
(2)myA is substitutable by A(myA is a sub type of A).

I tried to test second rule of substitution. Here's the code:

interface A{
void a();
}
-----------------
class myA implements A
{
public void a() {}

}
-----------------------
interface B{
void b(myA a);
}
--------------------------
class myB implements B{


public void b(A a) {


}
}

The news is I'm still having the error:
myB is not abstract and does not override abstract method b(myA) in B
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[Joe]: The news is I'm still having the error:
myB is not abstract and does not override abstract method b(myA) in B


If you look carefully, that's a slightly different error than your original one. And like the first error, it tells you exactly what is wrong with the current code. Quite simply, if you need to override b(myA), then b(A) is not close enough. (And vice versa, in the original problem.) To override a method, you need to use the exact same parameter types, period. (Well, it gets more complicated if generics are involved, but that's not relevant here.) If you change the parameter types - even if the ypes are related - you will get errors. So, don't change the parameter types.


"I'm not back." - Bill Harding, Twister
Joe Khan
Greenhorn

Joined: Aug 27, 2004
Posts: 15
Oh yea Jim, you are right..
sorry I missed that overriding stuff.
There's no such thing auto-conversion with method overriding . The return type and arguments list have to be exactly same.
Auto-conversion only occurs on assignements or on method calls with arugments.
Thank you all for replies.

[ December 17, 2007: Message edited by: Joe Khan ]
[ December 17, 2007: Message edited by: Joe Khan ]
 
 
subject: narrowing of type and interfaces
 
Similar Threads
Tricky question about polymorphism
Function returning two reference variables
Extracting certain parameters from objects
Inner class and misc Q
Accessspecifiers....................imp.....................