ambiguous reference and inheritance

Z

zoe

My compiler (JBuilder3) does not accept the code below.
But i can't find this te be illegal in the jaca spec.
Can anyone help?

public class MyClass1 {
public static void main(String[] args) {
DC dc= new DC();
Sub b=new Sub();
dc.g(b);
}
}
class BC{
void g(Sub d){}
}
class DC extends BC{
void g(Sup b){}
}
class Sup{}
class Sub extends Sup{}

How does de code above differ from:

class Test{
void foo(Sup b){}
void foo(Sub d){} //overloading
}

Test t=new Test();
t.foo(new Sub());

regards,
Zoe
 
F

fabio

zoe said:
My compiler (JBuilder3) does not accept the code below.
But i can't find this te be illegal in the jaca spec.
Can anyone help?

public class MyClass1 {
public static void main(String[] args) {
DC dc= new DC();
Sub b=new Sub();
dc.g(b);
}
}

Your compiler don't know who "g" have to call!
Both BC and Dc define a "g" function who take a Sup argument!
Remember that a Sub "is a" Sup

it work if you call with a cast
dc.g((Sup)b); // call DC.g()


bye
 
A

A. Bolmarcich

My compiler (JBuilder3) does not accept the code below.
But i can't find this te be illegal in the jaca spec.
Can anyone help?

public class MyClass1 {
public static void main(String[] args) {
DC dc= new DC();
Sub b=new Sub();
dc.g(b);
}
}
class BC{
void g(Sub d){}
}
class DC extends BC{
void g(Sup b){}
}
class Sup{}
class Sub extends Sup{}

See Section 15.12.2 "Compile-Time Step 2: Determine Method Signature"
of the Java Language Specification at

http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#289905

For the expression dc.g(b) two methods are applicable and accessible:
DC.g(Sup) and BC.g(Sub). However, neither method is more specific
that the other according to the definition of more specific method
in Section 15.12.2.2.
 
J

Joona I Palaste

fabio said:
zoe said:
My compiler (JBuilder3) does not accept the code below.
But i can't find this te be illegal in the jaca spec.
Can anyone help?

public class MyClass1 {
public static void main(String[] args) {
DC dc= new DC();
Sub b=new Sub();
dc.g(b);
}
}
Your compiler don't know who "g" have to call!
Both BC and Dc define a "g" function who take a Sup argument!
Remember that a Sub "is a" Sup
it work if you call with a cast
dc.g((Sup)b); // call DC.g()

How would you call the dc.g(Sub) method then? Like this?
dc.g((Sub)b);
 
F

fabio

Joona said:
fabio said:
zoe said:
My compiler (JBuilder3) does not accept the code below.
But i can't find this te be illegal in the jaca spec.
Can anyone help?

public class MyClass1 {
public static void main(String[] args) {
DC dc= new DC();
Sub b=new Sub();
dc.g(b);
}
}
Your compiler don't know who "g" have to call!
Both BC and Dc define a "g" function who take a Sup argument!
Remember that a Sub "is a" Sup
it work if you call with a cast
dc.g((Sup)b); // call DC.g()

How would you call the dc.g(Sub) method then? Like this?
dc.g((Sub)b);

No, You need a reference to a BC object ( I think )

bye
 
C

Chris Smith

fabio said:
public class MyClass1 {
public static void main(String[] args) {
DC dc= new DC();
Sub b=new Sub();
dc.g(b);
}
}
Your compiler don't know who "g" have to call!
Both BC and Dc define a "g" function who take a Sup argument!
Remember that a Sub "is a" Sup
it work if you call with a cast
dc.g((Sup)b); // call DC.g()

How would you call the dc.g(Sub) method then? Like this?
dc.g((Sub)b);

No, You need a reference to a BC object ( I think )

Fabio,

No, that's not the case. The runtime class of objects referred to by
method parameters are never used to resolve method dispatch. Only the
parameter types are significant. It turns out, actually, that you call
g(Sub) as follows:

((BC) dc).g(b);

(Incidentally, dc.g((Sub)b) can't do anything different from dc.g(b),
because the type of the two expressions "b" and "(Sub)b" are
identical... they are both expressions of type Sub.)

Personally, I think this is all rather silly, and I'd like to see the
justification for the restriction in 15.12.2.2 that T must be
convertable to U by method invocation conversion in order to make m in T
a maximally specific method.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

Joona I Palaste

Chris Smith said:
fabio wrote:

(I wrote:)
No, that's not the case. The runtime class of objects referred to by
method parameters are never used to resolve method dispatch. Only the
parameter types are significant. It turns out, actually, that you call
g(Sub) as follows:
((BC) dc).g(b);
(Incidentally, dc.g((Sub)b) can't do anything different from dc.g(b),
because the type of the two expressions "b" and "(Sub)b" are
identical... they are both expressions of type Sub.)

The OP's code:
public class MyClass1 {
public static void main(String[] args) {
DC dc= new DC();
Sub b=new Sub();
dc.g(b);
}
}
class BC{
void g(Sub d){}
}
class DC extends BC{
void g(Sup b){}
}
class Sup{}
class Sub extends Sup{}

Suppose the inheritance pairing was reversed, and the classes looked
like this:
class BC {
void g(Sup d) {}
}
class DC extends BC {
void g(Sub p) {}
}

Now, what would the call new DC().g(new Sub()) do? It is ambiguous,
because DCs have a g for both Sups and Subs. Therefore, if we want to
call the Sup version, we write new DC().g((Sup)new Sub()), but what
if we want to call the Sub version? Or is this ambiguiety handled by
the compiler with a "more specific" rule?
 
C

Chris Smith

Joona said:
Suppose the inheritance pairing was reversed, and the classes looked
like this:
class BC {
void g(Sup d) {}
}
class DC extends BC {
void g(Sub p) {}
}

Now, what would the call new DC().g(new Sub()) do?

It would call the method g(Sub), which is declared in class DC. There
is no ambiguity, because that is the only maximally specific method.
The ambiguity in the early case specifically resulted from the situation
where DC was more specific than BC, *but* the method g declared in the
less specific BC had a parameter type (Sub) that was more specific than
g's parameter type (Sup) in the more specific DC. So, by strange JLS
logic, there was something to recommend either decision, because each
choice was most specific in some way or another.

Your change removes that ambiguity, and there's no longer a problem.

So, in short:
Or is this ambiguiety handled by
the compiler with a "more specific" rule?

Yes, it is. You can simply say new DC().g(new Sub()) if you mean to
call g(Sub).

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

John C. Bollinger

Chris said:
Personally, I think this is all rather silly, and I'd like to see the
justification for the restriction in 15.12.2.2 that T must be
convertable to U by method invocation conversion in order to make m in T
a maximally specific method.

It's not the only way it could work, but it makes sense to me. In the
OP's case, there was a method defined in the superclass with a narrower
argument type and a method defined in the subclass with a broader
argument type, both applicable and accessible. If both were defined in
the subclass then the one with the narrower type would be the more
specific. If both had the same argument type then the one in the
subclass would be the more specific. To handle the OP's case, one of
two possible rules needs to be chosen, but I see no compelling argument
for choosing one over the other. Moreover, I can imagine scenarios
where each rule would be the one desired / expected. Rather than making
an arbitrary choice, Java disallows the ambiguity. I suspect Java's
approach here has saved more time in debugging than it has cost in
design and coding.


John Bollinger
(e-mail address removed)
 
C

Chris Smith

John said:
It's not the only way it could work, but it makes sense to me. In the
OP's case, there was a method defined in the superclass with a narrower
argument type and a method defined in the subclass with a broader
argument type, both applicable and accessible.
Right.

To handle the OP's case, one of
two possible rules needs to be chosen, but I see no compelling argument
for choosing one over the other.

That's just the thing. I see a very compelling reason, and that is that
a consistent picture of inheritance could be drawn in which inherited
methods are held on an equal level with methods declared or overridden
in a subclass. There's no reason to differentiate between the two based
on the location of the declaration or implementation code, unless (as I
suspect is the case for whoever came up with this rule) you don't really
believe in inheritance and are trying to water down its definition.

Luckily, this is just a fringe case where the impact is not often seen.
It takes a contrived example to bring it out. I'm glad that this isn't
the case in a situation where it actually matters.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
C

Chris Riesbeck

My compiler (JBuilder3) does not accept the code below.
But i can't find this te be illegal in the jaca spec.
Can anyone help?

public class MyClass1 {
public static void main(String[] args) {
DC dc= new DC();
Sub b=new Sub();
dc.g(b);
}
}
class BC{
void g(Sub d){}
}
class DC extends BC{
void g(Sup b){}
}
class Sup{}
class Sub extends Sup{}

See Section 15.12.2 "Compile-Time Step 2: Determine Method Signature"
of the Java Language Specification at

http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#289905

For the expression dc.g(b) two methods are applicable and accessible:
DC.g(Sup) and BC.g(Sub). However, neither method is more specific
that the other according to the definition of more specific method
in Section 15.12.2.2.

Umm, I agree with everything said here, but but but

I just compiled and ran the above code in JCreator using jdk1.4.2. It
called BC.g(Sub) method.

Have the rules in Section 15.12.2.2 changed?
 
D

Doug Pardee

Chris Smith said:
Personally, I think this is all rather silly, and I'd like to see the
justification for the restriction in 15.12.2.2 that T must be
convertable to U by method invocation conversion in order to make m in T
a maximally specific method.

Break out the champagne... that restriction was removed from the JLS
starting with Java 1.4.2.

See http://java.sun.com/docs/books/jls/clarifications-2-2nd-ed.html
for the exciting details! Well, okay, maybe not exciting. They simply
removed that requirement.

Doug Dunn seems to have a reasonably good discussion of the change on
JDJ: http://www.sys-con.com/story/?storyid=34292
 
C

Chris Riesbeck

Chris Smith said:
zoe coded:
[ class BC { g(Sub) ... }
class DC extends BC { g(Sup) ...}
class Sup
class Sub extends Sup
DC dc
Sub b
dc.g(b) ??? ]
... The runtime class of objects referred to by
method parameters are never used to resolve method dispatch. Only the
parameter types are significant. It turns out, actually, that you call
g(Sub) as follows:

((BC) dc).g(b);

For me, using jdsk1.4.2, dc.g(b) already calls BC.g(). And as
mentioned elsewhere, dc.g((Sup) b) calls DC.g().

But if we changed to code so that both BC and DC have, say,
g(Sub), then the above typecast has no effect. That is, both
dc.g(b) and ((BC) dc).g(b) call DC.g(), never BC.g().

Typecasts on parameters affect compile-time dispatch of
overloaded methods. Typecasts have no effect on run-time dispatch
of overridden methods.
 
C

Chris Smith

Doug said:
Break out the champagne... that restriction was removed from the JLS
starting with Java 1.4.2.

See http://java.sun.com/docs/books/jls/clarifications-2-2nd-ed.html
for the exciting details! Well, okay, maybe not exciting. They simply
removed that requirement.

Doug Dunn seems to have a reasonably good discussion of the change on
JDJ: http://www.sys-con.com/story/?storyid=34292

Great to hear it! :)

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

John C. Bollinger

Chris said:
John C. Bollinger wrote:


That's just the thing. I see a very compelling reason, and that is that
a consistent picture of inheritance could be drawn in which inherited
methods are held on an equal level with methods declared or overridden
in a subclass. There's no reason to differentiate between the two based
on the location of the declaration or implementation code, unless (as I
suspect is the case for whoever came up with this rule) you don't really
believe in inheritance and are trying to water down its definition.

Now that I think about it more, I see your point. Well and good that
the rule is lifted.


John Bollinger
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top