Quick inheritance question

Discussion in 'Java' started by Will Clark, Aug 23, 2003.

  1. Will Clark

    Will Clark Guest

    I have a class such as:

    class A
    {
    public void methodA()
    {
    // does general stuff and also:

    methodB();
    }

    public void methodB()
    {
    // Does something non-descript!
    }
    }

    and another class that is a subclass of this, for example:

    class B extends A
    {
    public void methodA()
    {
    // Does stuff and then...

    super.methodA();
    }

    public void methodB()
    {
    // Does something or other and then...

    methodA();
    }
    }

    Now if I were to create an instance of class B and call methodB on it, such
    as in the following fragment:

    B obj;
    obj.methodB();

    I would like it to run, in the following order:

    B.methodB()
    B.methodA()
    A.methodA()
    A.methodB()

    end then stop! But it doesn't because instead A.methodA() goes and calls
    B.methodB() not A.methodB() and the whole thing sits in a loop.

    Is there any way of indicating to Java that A.methodA() calls A.methodB()
    and NOT the inherited version of it?

    Cheers for your help!

    Will
    Will Clark, Aug 23, 2003
    #1
    1. Advertising

  2. Will Clark <> scribbled the following:
    > I have a class such as:


    > class A
    > {
    > public void methodA()
    > {
    > // does general stuff and also:


    > methodB();
    > }


    > public void methodB()
    > {
    > // Does something non-descript!
    > }
    > }


    > and another class that is a subclass of this, for example:


    > class B extends A
    > {
    > public void methodA()
    > {
    > // Does stuff and then...


    > super.methodA();
    > }


    > public void methodB()
    > {
    > // Does something or other and then...


    > methodA();
    > }
    > }


    > Now if I were to create an instance of class B and call methodB on it, such
    > as in the following fragment:


    > B obj;
    > obj.methodB();


    > I would like it to run, in the following order:


    > B.methodB()
    > B.methodA()
    > A.methodA()
    > A.methodB()


    > end then stop! But it doesn't because instead A.methodA() goes and calls
    > B.methodB() not A.methodB() and the whole thing sits in a loop.


    > Is there any way of indicating to Java that A.methodA() calls A.methodB()
    > and NOT the inherited version of it?


    No. Instance methods always use the most specific implementation, i.e.
    furthest down in the inheritance tree. You'll have to use a real
    instance of A (not just a B pretending to be an A) or make the methods
    static.

    > Cheers for your help!


    > Will








    --
    /-- Joona Palaste () ---------------------------\
    | Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
    | http://www.helsinki.fi/~palaste W++ B OP+ |
    \----------------------------------------- Finland rules! ------------/
    "O pointy birds, O pointy-pointy. Anoint my head, anointy-nointy."
    - Dr. Michael Hfuhruhurr
    Joona I Palaste, Aug 23, 2003
    #2
    1. Advertising

  3. Joona I Palaste () wrote:
    : No. Instance methods always use the most specific implementation, i.e.
    : furthest down in the inheritance tree. You'll have to use a real
    : instance of A (not just a B pretending to be an A) or make the methods
    : static.

    I can think of one thing that may work (I have not tested this so I am
    not certain that it works). With reflection it is possible to find the
    super class method and it should be possible to call that
    method. Using reflections for this case is _not_ recomended, but it
    may work.
    Anyone care to test?

    /robo
    Robert Olofsson, Aug 24, 2003
    #3
  4. On Sun, 24 Aug 2003 00:24:08 GMT, David E. wrote:
    >couldn't he (in the "3rd step") use casting somehow to call methodB of class
    >A?


    You can use super.method() to call a method of the class it inherited.


    --
    Gerbrand van Dieijen

    WWW: http://twisted.warande.net
    ICQ: 19345450
    Gerbrand van Dieijen, Aug 25, 2003
    #4
  5. Will Clark wrote:
    >
    > I have a class such as:
    >
    > class A
    > {
    > public void methodA()
    > {
    > // does general stuff and also:
    >
    > methodB();
    > }
    >
    > public void methodB()
    > {
    > // Does something non-descript!
    > }
    > }
    >
    > and another class that is a subclass of this, for example:
    >
    > class B extends A
    > {
    > public void methodA()
    > {
    > // Does stuff and then...
    >
    > super.methodA();
    > }
    >
    > public void methodB()
    > {
    > // Does something or other and then...
    >
    > methodA();
    > }
    > }
    >
    > Now if I were to create an instance of class B and call methodB on it, such
    > as in the following fragment:
    >
    > B obj;
    > obj.methodB();
    >
    > I would like it to run, in the following order:
    >
    > B.methodB()
    > B.methodA()
    > A.methodA()
    > A.methodB()
    >
    > end then stop! But it doesn't because instead A.methodA() goes and calls
    > B.methodB() not A.methodB() and the whole thing sits in a loop.
    >
    > Is there any way of indicating to Java that A.methodA() calls A.methodB()
    > and NOT the inherited version of it?
    >
    > Cheers for your help!
    >
    > Will


    the easy way is to create a third method in class A:
    class A
    {
    public void methodA()
    {
    // does general stuff and also:

    methodC();
    }

    public void methodB()
    {
    methodC();
    }

    private void methodC()
    {
    // Does the real stuff for classA's methodB
    }
    }

    --
    Fred L. Kleinschmidt
    Associate Technical Fellow
    Boeing Common User Interface Services
    Fred L. Kleinschmidt, Aug 26, 2003
    #5
  6. Will Clark

    Will Clark Guest

    I agree that your solution is the only way you can do it using the Java
    compiler. I have come to the conclusion that it appears to be a "limitation"
    of the Java compiler, because my tests have indicated that it is possible if
    you modify the call at the bytecode level.

    Java does a "invokevirtual" to call a method, and it calls whatever
    overrides the virtual method in class A with the method in class B, causing
    the infinite loop.

    However, if the "invokevirtual" instruction is replaced with "invokespecial"
    or "invokenonvirtual" then it works as needed.

    (I have attached three source files - A.java and a rewritten A.jasm (for the
    Jasmin bytecode assembler, and B.java - and the compiled class files. Try
    running "java B" and the behaviour is correct.)

    Does anyone know of any short comings to using this approach? According to
    the official VM specs "invokespecial" is mainly for use in calling <init> or
    when compiling the 'super' keyword. And "invokenonvirtual" doesn't seem to
    be documented anywhere...

    Will

    P.S. perhaps it would be nice if an up-and-coming Java compiler could add a
    keyword that invokes a method as though it were non overriden?! (A
    'me.methodB()' construction perhaps!)
    Will Clark, Aug 27, 2003
    #6
    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. maxw_cc
    Replies:
    1
    Views:
    3,135
    Martijn van Steenbergen
    Dec 21, 2003
  2. JKop
    Replies:
    11
    Views:
    873
  3. cppsks
    Replies:
    0
    Views:
    815
    cppsks
    Oct 27, 2004
  4. karthikbalaguru
    Replies:
    9
    Views:
    1,036
  5. Daniel Pitts
    Replies:
    27
    Views:
    1,894
    Mike Schilling
    Feb 27, 2008
Loading...

Share This Page