Quick inheritance question

W

Will Clark

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
 
J

Joona I Palaste

Will Clark said:
I have a class such as:
class A
{
public void methodA()
{
// does general stuff and also:

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

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

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:

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!







--
/-- Joona Palaste ([email protected]) ---------------------------\
| 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
 
R

Robert Olofsson

Joona I Palaste ([email protected]) 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
 
G

Gerbrand van Dieijen

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

Fred L. Kleinschmidt

Will said:
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
}
}
 
W

Will Clark

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!)
 

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,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top