Question

I have an abstract class like so:

public abstract class MyAbstractClass {

    protected String greeting;

    public void run() {
        doSomething();
    }

    public abstract void doSomething();
}

... and a subclass like so:

public class MyClass extends MyAbstractClass {

    public MyClass() {
        this.greeting = "Hello, World!";
    }

    public void doSomething() {
        System.out.println(greeting);
    }

    public static void main(String[] args) {
        MyAbstractClass c = new MyClass();
        c.run();
    }
}

I'm going to be creating multiple subclasses, all of them will have the same main method that just instantiates the subclass. Is there a cleaner way of writing this so I don't need to duplicate the main method in every subclass with a different subclass name? So if I create a new subclass called MyOtherClass I don't need to put a main method in with MyAbstractClass c = new MyOtherClass();

I guess I can do it the other way round, where I run the main from the abstract class and instantiate the subclass in there, but then each time I want to change which subclass is instantiated I'd obviously need to change the class name after new. I suppose what I'm looking for is a way to define the main method in the abstract class in such a way that when I run the subclass, it instantiates a copy of the subclass and not the abstract class. If that makes sense...

Was it helpful?

Solution

This seems like a good fit for the factory method pattern. Try something like this:

public abstract class MyAbstractClass {

    protected String greeting;

    public void run() {
        doSomething();
    }

    public abstract void doSomething();

    public abstract MyAbstractClass makeClass();

}

public class MyClass1 extends MyAbstractClass {

    public MyClass1() {
        this.greeting = "Hello, World!";
    }

    @Override
    public void doSomething() {
        System.out.println(greeting);
    }

    @Override
    public MyAbstractClass makeClass() {
        return new MyClass1();
    }

}

Then, whenever you need to create a specific instance just call makeClass() in a single implementation of the main() method located in the place you consider most convenient, for instance in MyAbstractClass:

MyAbstractClass mac = new MyClass1();
MyAbstractClass obj = mac.makeClass();

The last line will return an appropriate instance depending on the class used for instantiating the concrete object.

OTHER TIPS

This is where dynamic class loading can be useful. If all your subclasses agree to have a no-arg constructor, you can simply use a single Main class with the main method, and pass the class to use as argument:

java com.foo.bar.Main com.foo.bar.MyFrouteenthSubclass

The main method would simply look like this:

public static void main(String[] args) throws Exception {
    String className = args[0];
    MyAbstractClass object = (MyAbstractClass) Class.forName(className).newInstance();
    object.run();
}

You could also assign a name to all your subclasses and store on instance of each of them in a Map<String, MyAbstractClass>, and simply call the main class with the name of the class as argument:

java com.foo.bar.Main fourteen
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top