8

I need to extend the functionality of my main class, by overriding some of its methods. I was expecting that the class extending the main class would be able to be run. However, Eclipse doesn't recognize MyLauncher as a runnable class. In the following code, I have a setup() method that is overridden by the subclass. What I want is a way to run the main(..) from the super class but also the setup from the subclass.

// Launcher.java
public class Launcher {

    Launcher instance;

    public static void main (args[]) {
        instance = new Launcher(); // This is likely the problem
        instance.setup();
    }

    public void setup() {
        System.out.println("Default agent setup.");
    }
}

// MyLauncher.java
public class MyLauncher extends Launcher {

    public void setup() {
        System.out.println("New agent setup!");
    }
}

I accept alternatives to this. I can't add a main method to the subclass, though. The Launcher class is inside an API i'm making, so it can't refer to the class MyLauncher that is using the API.

edit: I think this is to specific to my problem. I decided to search for a new approach. Since I'm working with JDT, I'm going to parse the Launcher and inject the class.

ecc
  • 1,490
  • 1
  • 17
  • 42
  • Aside from anything else, it would really help if you'd post *actual* code rather than *pseudocode*. The current code needs a number of tweaks before it will compile. – Jon Skeet May 14 '14 at 13:42
  • 3
    The main method is static. So, `MyLauncher` is not a runnable class because it doesn't have a main method. – William Morrison May 14 '14 at 13:42
  • Yes, I realize that much. But, I don't think that is my core problem. Before instanciating, the type of the class running the main is already Launcher. I only need to instanciate because I need to override the `setup()` – ecc May 14 '14 at 13:44
  • @William, Right :/ Is there no way to do it, though? – ecc May 14 '14 at 13:45
  • in your actual compilable code put `instance = new MyLauncher()` and run your Launcher class. – Sanjeev May 14 '14 at 13:47
  • Launcher is inside an API and can't refer to MyLauncher. Sorry for the lack of details in the OP. – ecc May 14 '14 at 13:53
  • 1
    Its best not to consider the main method to be anywhere in particular. It is in one class file because "it has to be somewhere" putting too much emphasis on which class file can be dangerous. – Richard Tingle May 14 '14 at 13:54
  • 1
    See also http://stackoverflow.com/questions/10291949/are-static-methods-inherited-in-java – Raedwald May 21 '14 at 07:18

5 Answers5

8

Static methods are not inherited, they're always bound to the class that defines them, and need to be called explicitely.

In you case, the MyLauncher needs a main() method too, and could then delegate to the main() method of Launcher:

public class MyLauncher extends Launcher {

    public static void main (String[] args) {
        Launcher.main(args);
    }

    protected void setup() {
        System.out.println("New agent setup!");
    }
}
Peter Walser
  • 15,208
  • 4
  • 51
  • 78
2

Protected methods can not be called from outside. So the MyLauncher.setup() do not override Launcher.setup() and instance.setup(); calls the public method from Class Launcher.

Grim
  • 1,938
  • 10
  • 56
  • 123
2

There can only be one main method in your project, that is one entry point to the program. So let's assume you're going to be keeping the main method in the Launcher class.

Your main method signature should be:

public static void main (String args[])

And unless you want the setup() method from the launcher to be called you'd want to do:

instance = new MyLauncher();

That would call the setup() method from MyLauncher.

If you want to call setup() from the Launcher class you need to instantiate the launcher class:

instance = new Launcher();
Eidan Spiegel
  • 307
  • 1
  • 2
  • 10
  • 2
    I can have multiple main methods in my project. I can just select which one I want to run. I can't have references to MyLauncher in the Launcher, though, because MyLauncher is inside an API I'm making. – ecc May 14 '14 at 13:47
2

If you want to be able to run MyLauncher.setup(), the variable must be a MyLauncher. You are initializing and storing a Launcher in the main() function.

If the two classes are in the same package, or Launcher.java imports the MyLauncher class, then the main() function in Launcher should be able to be:

public class Launcher {
    Launcher instance;

    public static void main(String[] args) {
        instance = new MyLauncher();
        if(instance instanceof MyLauncher) {
            ((MyLauncher) instance).setup();
        } else
        {
            instance.setup();
        }
    }
}
Tripp Kinetics
  • 5,178
  • 2
  • 23
  • 37
1

As you say, the fact that you create an instance of Launcher directly in main means that no inheritance is available. Even if you could start MyLauncher easily from Eclipse, within the main method you wouldn't know which type had actually been used to start it. I can't see any easy solution that doesn't involve either creating a main method in each class or providing the class name as a command-line argument. I would probably separate the "running" from anything else:

public class Launcher {
    public static void launch(LaunchConfiguration configuration) {
        configuration.setup();
        ...
    }
}

public class LaunchConfiguration {
    public static void main(String[] args) {
        Launcher.launch(new LaunchConfiguration());
    }

    public void setup() {
    }
}

public class MyLaunchConfiguration {
    public static void main(String[] args) {
        Launcher.launch(new MyLaunchConfiguration());
    }

    @Override
    public void setup() {
    }
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194