Accessing grandparent's overridden methods.

Discussion in 'Java' started by Kira Yamato, Jan 1, 2008.

  1. Kira Yamato

    Kira Yamato Guest

    class A
    {
    public int showMe() { System.out.println("A"); }
    }

    class B extends A
    {
    public int showMe() { System.out.println("B"); }
    }

    class C extends A
    {
    public int showMe() { System.out.println("C"); }

    public void test()
    {
    showMe(); // prints C
    super.showMe(); // prints B

    // Question: how can I access class A's showMe()?
    // I'm suspecting this cannot be done without modifying codes
    outside of class C.
    }
    }

    Thanks.

    --

    -kira
     
    Kira Yamato, Jan 1, 2008
    #1
    1. Advertising

  2. Kira Yamato

    Mark Rafn Guest

    [ B extends A, C extends B, each implements/overrides showMe() ]

    Kira Yamato <> wrote:
    > Question: how can I [in class C] access class A's showMe()?
    > I'm suspecting this cannot be done without modifying codes
    > outside of class C.


    1) if you need to do this, you've probably got a broken object model. You
    shouldn't know or care about it's implementation beyond what method signatures
    are available to you.

    2) If you really need it, you could use reflection.
    this.getClass().getSuperclass().getSuperclass().getMethod("showMe", null)
    will get you the Method you want to call.
    --
    Mark Rafn <http://www.dagon.net/>
     
    Mark Rafn, Jan 1, 2008
    #2
    1. Advertising

  3. Kira Yamato <> writes:

    > class A
    > {
    > public int showMe() { System.out.println("A"); }
    > }
    >
    > class B extends A
    > {
    > public int showMe() { System.out.println("B"); }
    > }
    >
    > class C extends A


    You mean "extends B" for the question to make sense.

    > {
    > public int showMe() { System.out.println("C"); }
    >
    > public void test()
    > {
    > showMe(); // prints C
    > super.showMe(); // prints B
    >
    > // Question: how can I access class A's showMe()?


    You can't.
    Perhaps using reflection, but that's sidestepping a restriction
    that is there for a reason.

    A more relevant question is: Why do you want to? Should you instead
    change your model or class hierarchy so that it matches what you want
    to do with it?

    > // I'm suspecting this cannot be done without modifying codes
    > outside of class C.


    Correct.

    /L
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, Jan 1, 2008
    #3
  4. Mark Rafn wrote:
    > [ B extends A, C extends B, each implements/overrides showMe() ]
    >
    > Kira Yamato <> wrote:
    >> Question: how can I [in class C] access class A's showMe()?
    >> I'm suspecting this cannot be done without modifying codes
    >> outside of class C.

    >
    > 1) if you need to do this, you've probably got a broken object model. You
    > shouldn't know or care about it's implementation beyond what method signatures
    > are available to you.


    Strongly agree. Either C should not be calling A's method, or B's
    version does not do the same job as A's method, and should have a
    different name.


    > 2) If you really need it, you could use reflection.
    > this.getClass().getSuperclass().getSuperclass().getMethod("showMe", null)
    > will get you the Method you want to call.


    This does not seem to work. However, to be fair, I was not really
    expecting it to work so I may have missed something. Please review. I get:

    Direct showMe call
    C
    Super call
    B
    Refection call
    C

    when I run the following. Note that I would only throw "Exception" in a
    test program, where I want any problem in the reflection, no matter what
    it is, to flow to the top and crash the program.

    public class ReflectionTest {

    public static void main(String[] args)
    throws Exception {
    new C().test();
    }

    static class A {
    public void showMe() {
    System.out.println("A");
    }
    }

    static class B extends A {
    public void showMe() {
    System.out.println("B");
    }
    }

    static class C extends B {
    public void showMe() {
    System.out.println("C");
    }

    public void test() throws Exception {
    System.out.println("Direct showMe call");
    showMe(); // prints C
    System.out.println("Super call");
    super.showMe(); // prints B
    System.out.println("Refection call");
    Method grandparentMethod =
    getClass().getSuperclass().getSuperclass()
    .getMethod("showMe", (Class[]) null);
    grandparentMethod.invoke(this, new Object[0]);
    }
    }

    }
     
    Patricia Shanahan, Jan 2, 2008
    #4
  5. Kira Yamato

    Kira Yamato Guest

    On 2008-01-01 18:35:43 -0500, Lasse Reichstein Nielsen <> said:

    > Kira Yamato <> writes:
    >
    >> class A
    >> {
    >> public int showMe() { System.out.println("A"); }
    >> }
    >>
    >> class B extends A
    >> {
    >> public int showMe() { System.out.println("B"); }
    >> }
    >>
    >> class C extends A

    >
    > You mean "extends B" for the question to make sense.
    >
    >> {
    >> public int showMe() { System.out.println("C"); }
    >>
    >> public void test()
    >> {
    >> showMe(); // prints C
    >> super.showMe(); // prints B
    >>
    >> // Question: how can I access class A's showMe()?

    >
    > You can't.
    > Perhaps using reflection, but that's sidestepping a restriction
    > that is there for a reason.
    >
    > A more relevant question is: Why do you want to?


    I don't. It's just an academic question.

    > Should you instead
    > change your model or class hierarchy so that it matches what you want
    > to do with it?


    And you're right. In a proper design, I should've given these methods
    different signature so that I can differentiate them in class C.

    >
    >> // I'm suspecting this cannot be done without modifying codes
    >> outside of class C.

    >
    > Correct.


    Thanks.

    --

    -kira
     
    Kira Yamato, Jan 2, 2008
    #5
  6. Kira Yamato

    Kira Yamato Guest

    On 2008-01-01 18:18:09 -0500, (Mark Rafn) said:

    > [ B extends A, C extends B, each implements/overrides showMe() ]
    >
    > Kira Yamato <> wrote:
    >> Question: how can I [in class C] access class A's showMe()?
    >> I'm suspecting this cannot be done without modifying codes
    >> outside of class C.

    >
    > 1) if you need to do this, you've probably got a broken object model. You
    > shouldn't know or care about it's implementation beyond what method signatures
    > are available to you.


    Good point. I'm just trying to readjust from the C++ mindset here.

    >
    > 2) If you really need it, you could use reflection.
    > this.getClass().getSuperclass().getSuperclass().getMethod("showMe", null)
    > will get you the Method you want to call.


    I think the dynamic method lookup mechanism would still cause the
    program to give me C's version of the method again.

    Anyway, it was just an academic question. As you pointed out, a proper
    object design should not require this need.

    Thanks.

    --

    -kira
     
    Kira Yamato, Jan 2, 2008
    #6
  7. Kira Yamato

    Mark Rafn Guest

    Patricia Shanahan <> wrote:
    >This does not seem to work. However, to be fair, I was not really
    >expecting it to work so I may have missed something. Please review. I get:


    You're right - this won't work. You'll ALWAYS invoke the appropriate showMe()
    for the object passed as the first argument of invoke(), regardless of which
    ancestor class you got the Method from.

    Good :)

    --
    Mark Rafn <http://www.dagon.net/>
     
    Mark Rafn, Jan 2, 2008
    #7
  8. Kira Yamato

    proudbug Guest

    On Jan 1, 11:18 pm, (Mark Rafn) wrote:
    > Patricia Shanahan  <> wrote:
    >
    > >This does not seem to work. However, to be fair, I was not really
    > >expecting it to work so I may have missed something. Please review. I get:

    >
    > You're right - this won't work.  You'll ALWAYS invoke the appropriate showMe()
    > for the object passed as the first argument of invoke(), regardless of which
    > ancestor class you got the Method from.
    >
    > Good :)
    >
    > --
    > Mark Rafn        <http://www.dagon.net/>  


    To make it work, you just need to use "new A()" as the first argument
    of invoke(), instead of "this".
     
    proudbug, Jan 2, 2008
    #8
  9. proudbug wrote:
    > On Jan 1, 11:18 pm, (Mark Rafn) wrote:
    >> Patricia Shanahan <> wrote:
    >>
    >>> This does not seem to work. However, to be fair, I was not really
    >>> expecting it to work so I may have missed something. Please review. I get:

    >> You're right - this won't work. You'll ALWAYS invoke the appropriate showMe()
    >> for the object passed as the first argument of invoke(), regardless of which
    >> ancestor class you got the Method from.
    >>
    >> Good :)
    >>
    >> --
    >> Mark Rafn <http://www.dagon.net/>

    >
    > To make it work, you just need to use "new A()" as the first argument
    > of invoke(), instead of "this".


    It depends what you mean by "work". In this, extremely simple, situation
    all instances of A do exactly the same thing on showMe() call.

    In more realistic situations, a new A() would not necessarily produce
    the behavior of the A showMe for the the C instance doing the call.

    Patricia
     
    Patricia Shanahan, Jan 2, 2008
    #9
  10. Kira Yamato wrote:
    > // Question: how can I access class A's showMe()?


    The short answer, as others have answered, you can't.
    The longer, more esoteric answer:
    The Java bytecode has two [*] means of calling non-static methods:
    invokevirtual and invokespecial (or invokenonvirtual). The difference
    between the two is in how the VM selects the method to invoke: the
    virtual one starts its way from the "runtime class" and works up to find
    the method, the latter from the "compile-time class" (not the most
    precise terms).

    When a method is called in Java, the compiler selects the virtual flavor
    except in one of two circumstances:
    1. The method is private.
    2. The method is called using super.

    In the latter case, only one super can appear (so super.super is not
    possible). This means in practice that the only control one has in the
    second case is to choose nonvirtual methods based on the immediate
    superclass and not other ancestors, a limitation not present in the
    bytecode.

    In short: it's possible if you're directly writing the bytecode.

    [*] There are five invoke opcodes: invokespecial, invokevirtual,
    invokeinterface, invokestatic, and invokedynamic. The latter are
    excluded because invokeinterface is essentially an invokevirtual,
    invokestatic uses static methods which do not inherit, and invokedynamic
    is an opcode for languages over than Java.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
     
    Joshua Cranmer, Jan 2, 2008
    #10
  11. Kira Yamato

    Kira Yamato Guest

    On 2008-01-02 18:39:58 -0500, Joshua Cranmer <> said:

    > Kira Yamato wrote:
    >> // Question: how can I access class A's showMe()?

    >
    > The short answer, as others have answered, you can't.
    > The longer, more esoteric answer:
    > The Java bytecode has two [*] means of calling non-static methods:
    > invokevirtual and invokespecial (or invokenonvirtual). The difference
    > between the two is in how the VM selects the method to invoke: the
    > virtual one starts its way from the "runtime class" and works up to
    > find the method, the latter from the "compile-time class" (not the most
    > precise terms).
    >
    > When a method is called in Java, the compiler selects the virtual
    > flavor except in one of two circumstances:
    > 1. The method is private.
    > 2. The method is called using super.
    >
    > In the latter case, only one super can appear (so super.super is not
    > possible). This means in practice that the only control one has in the
    > second case is to choose nonvirtual methods based on the immediate
    > superclass and not other ancestors, a limitation not present in the
    > bytecode.
    >
    > In short: it's possible if you're directly writing the bytecode.
    >
    > [*] There are five invoke opcodes: invokespecial, invokevirtual,
    > invokeinterface, invokestatic, and invokedynamic. The latter are
    > excluded because invokeinterface is essentially an invokevirtual,
    > invokestatic uses static methods which do not inherit, and
    > invokedynamic is an opcode for languages over than Java.


    Thanks for the information on the inner workings of java. I have
    subsequently found the java 3.0 spec. and am currently studying it.

    --

    -kira
     
    Kira Yamato, Jan 3, 2008
    #11
  12. Kira Yamato

    Lew Guest

    Kira Yamato wrote:
    > Thanks for the information on the inner workings of java. I have
    > subsequently found the java 3.0 spec. and am currently studying it.


    Do you mean /The Java Language Specification, Third Edition/,
    <http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html>
    ?

    There is no such thing as a "java 3.0 spec".

    --
    Lew
     
    Lew, Jan 3, 2008
    #12
  13. Kira Yamato

    Kira Yamato Guest

    On 2008-01-03 01:10:33 -0500, Lew <> said:

    > Kira Yamato wrote:
    >> Thanks for the information on the inner workings of java. I have
    >> subsequently found the java 3.0 spec. and am currently studying it.

    >
    > Do you mean /The Java Language Specification, Third Edition/,
    > <http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html>
    > ?


    Yes, that's right. The java language specification, 3rd edition.

    --

    -kira
     
    Kira Yamato, Jan 3, 2008
    #13
  14. Kira Yamato

    proudbug Guest

    On Jan 2, 12:14 pm, Patricia Shanahan <> wrote:
    > proudbug wrote:
    > > On Jan 1, 11:18 pm, (Mark Rafn) wrote:
    > >> Patricia Shanahan  <> wrote:

    >
    > >>> This does not seem to work. However, to be fair, I was not really
    > >>> expecting it to work so I may have missed something. Please review. I get:
    > >> You're right - this won't work.  You'll ALWAYS invoke the appropriate showMe()
    > >> for the object passed as the first argument of invoke(), regardless of which
    > >> ancestor class you got the Method from.

    >
    > >> Good :)

    >
    > >> --
    > >> Mark Rafn        <http://www.dagon.net/>  

    >
    > > To make it work, you just need to use "new A()" as the first argument
    > > of invoke(), instead of "this".

    >
    > It depends what you mean by "work". In this, extremely simple, situation
    > all instances of A do exactly the same thing on showMe() call.
    >
    > In more realistic situations, a new A() would not necessarily produce
    > the behavior of the A showMe for the the C instance doing the call.
    >
    > Patricia- Hide quoted text -
    >

    I see your point. Thanks.
     
    proudbug, Jan 3, 2008
    #14
    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. Marco
    Replies:
    7
    Views:
    9,219
    Alex Hunsley
    Sep 13, 2004
  2. Replies:
    15
    Views:
    13,930
    Chris Uppal
    Sep 24, 2004
  3. Milan Gornik

    Exceptions and overridden methods

    Milan Gornik, Mar 29, 2005, in forum: C++
    Replies:
    1
    Views:
    2,952
    lilburne
    Mar 29, 2005
  4. Martin Manns

    grandparent method with super

    Martin Manns, Apr 5, 2007, in forum: Python
    Replies:
    10
    Views:
    532
    Bruno Desthuilliers
    Apr 6, 2007
  5. Bryan Ray

    accessing overridden methods

    Bryan Ray, Dec 6, 2003, in forum: Javascript
    Replies:
    1
    Views:
    105
    Lasse Reichstein Nielsen
    Dec 6, 2003
Loading...

Share This Page