ambiguous reference and inheritance

Discussion in 'Java' started by zoe, Dec 16, 2003.

  1. zoe

    zoe Guest

    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
     
    zoe, Dec 16, 2003
    #1
    1. Advertising

  2. zoe

    fabio Guest

    zoe wrote:

    > 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
     
    fabio, Dec 16, 2003
    #2
    1. Advertising

  3. In article <>, zoe wrote:
    > 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.
     
    A. Bolmarcich, Dec 16, 2003
    #3
  4. fabio <> scribbled the following:
    > zoe wrote:
    >> 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);

    --
    /-- Joona Palaste () ------------- Finland --------\
    \-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
    "To err is human. To really louse things up takes a computer."
    - Anon
     
    Joona I Palaste, Dec 16, 2003
    #4
  5. zoe

    fabio Guest

    Joona I Palaste wrote:

    > fabio <> scribbled the following:
    >> zoe wrote:
    >>> 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
     
    fabio, Dec 16, 2003
    #5
  6. zoe

    Chris Smith Guest

    fabio wrote:
    > >>> 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
     
    Chris Smith, Dec 16, 2003
    #6
  7. Chris Smith <> scribbled the following:
    > fabio wrote:


    (I wrote:)
    >> > 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.)


    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?

    --
    /-- Joona Palaste () ------------- Finland --------\
    \-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
    "To doo bee doo bee doo."
    - Frank Sinatra
     
    Joona I Palaste, Dec 16, 2003
    #7
  8. zoe

    Chris Smith Guest

    Joona I Palaste wrote:
    > 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
     
    Chris Smith, Dec 17, 2003
    #8
  9. Chris Smith wrote:
    > 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
     
    John C. Bollinger, Dec 17, 2003
    #9
  10. zoe

    Chris Smith Guest

    John C. Bollinger wrote:
    > 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
     
    Chris Smith, Dec 17, 2003
    #10
  11. 9.net (A. Bolmarcich) wrote in message news:<9.net>...
    > In article <>, zoe wrote:
    > > 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?
     
    Chris Riesbeck, Dec 17, 2003
    #11
  12. zoe

    Doug Pardee Guest

    Chris Smith <> wrote:
    > 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
     
    Doug Pardee, Dec 17, 2003
    #12
  13. Chris Smith <> wrote in message news:<4.net>...
    > 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.
     
    Chris Riesbeck, Dec 17, 2003
    #13
  14. zoe

    Chris Smith Guest

    Doug Pardee wrote:
    > Chris Smith <> wrote:
    > > 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


    Great to hear it! :)

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

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
     
    Chris Smith, Dec 17, 2003
    #14
  15. Chris Smith wrote:

    > John C. Bollinger wrote:


    >>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.


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


    John Bollinger
     
    John C. Bollinger, Dec 18, 2003
    #15
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    2
    Views:
    1,046
  2. LaCo
    Replies:
    5
    Views:
    1,738
    Roedy Green
    May 13, 2004
  3. Peter Meier
    Replies:
    5
    Views:
    576
    Andrew McDonagh
    Nov 14, 2005
  4. nguillot
    Replies:
    5
    Views:
    735
    itaj sherman
    Feb 24, 2011
  5. Simon

    Ambiguous reference between X and Y problem

    Simon, Mar 14, 2009, in forum: ASP .Net Web Services
    Replies:
    2
    Views:
    1,262
Loading...

Share This Page