Cerin
Cerin

Reputation: 64901

Overriding a Java Method

I'm new to Java, and I've read over some tutorials on overriding methods, but an example I'm looking at isn't working the way I expect. For example, I have the code:

public class A{
    public void show(){
        System.out.println("A");
    }
    public void run(){
        show();
    }
    public static void main( String[] arg ) {
        new A().run();
    }
}
public class B extends A{
    @Override
    public void show(){
        System.out.println("B");
    }
}

When I instantiate and call B.run(), I would expect to see "B" outputted. However, I see "A" instead. What am I doing wrong?

Edit: Yes, the classes are in two separate files. They're shown together for brevity.

Edit: I'm not sure how B is being instantiated, as it's being done by a third-party program using a classloader.

Edit: More info on the third-party program. It starts by calling A.main(), which I didn't initially show (sorry). I'm assuming I need to make "new A().run();" more generic to use the name of the current class. Is that possible?

Upvotes: 5

Views: 458

Answers (6)

T.J. Crowder
T.J. Crowder

Reputation: 1075755

That code will output B if you:

(new B()).run();

Whatever the problem is, it's not in the code you've quoted.

Updated (after your edit)

If the third-party program is calling A.main(), there's nothing (reasonable) you can do in B that will inject itself into A. As long as A.main is doing new A().run(), it's going to have an instance of A, not an instance of B. There's no "current class name" to use, or if there is (depends on your point of view), it's A, not B.

You'll have to get the third-party program to call B in some way, rather than A, or just modify A directly (e.g., getting rid of B entirely). You do not want to modify A to make it use B; that tightly binds it to a descendant and makes the separation between them largely pointless.

Hope that helps.

Upvotes: 6

Laurent K
Laurent K

Reputation: 3533

If your external program instantiates A, you will have A, not B.

But you can try something like this, using some reflection, and pass "com.mypackage.A" or "com.mypackage.B" as arguments to your program.

With this code (exception catch missing), you will be able to print "A" or "B" depending on the string parameter that you pass.

public static void main( String[] arg ) {
    String className = arg[0];
    Class myClass  = Class.forName(className);
    Constructor cons = myClass.getConstructor(new Class[0]);
    A myObject = (A) cons.newInstance(new Object[0]);
    myObject.show();

}

Upvotes: 1

Michael Krauklis
Michael Krauklis

Reputation: 3954

I tried your example and my output was B.

How are you instantiating? Here's the exact code I ran.

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

        public void run() {
            show();
        }
    }

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

    public static void main(String args[]) {
        A a = new B();

        a.run();
    }
}

Upvotes: 1

KLE
KLE

Reputation: 24169

I tried, putting your two classes in two files, and it worked nicely, outputting "B". I called :

 B b = new B();
 b.run();

UPDATED : Also works as (because it is the same runtime instance):

 A a = new B();
 a.run();

Upvotes: 3

Nathan Hughes
Nathan Hughes

Reputation: 96454

Works for me.

Here's my code for A and B:

package so;

public class A{
    public void show(){
        System.out.println("A");
    }
    public void run(){
        show();
    }
}

class B extends A{
    @Override
    public void show(){
        System.out.println("B");
    }
}

Here's my entry point:

package so;

public class EntryPoint {

    public static void main(String[] args) {
        B b = new B();
        b.run();
    }
}

It prints out 'B'.

Upvotes: 2

ceth
ceth

Reputation: 45325

It depends of instantiating. Try this:

 A v1 = new A();
 A v2 = new B();
 B v3 = new A();
 B v4 = new B();

 v1.run()
 v2.run()
 v3.run()
 v4.run()

Upvotes: 1

Related Questions