If you actually still want main in each class, but have SuperFoo create the subclass instance and call bar(), you can do this with method references, and a Supplier<SuperFoo>
class SuperFoo {
static void create(Supplier<SuperFoo> supplier) {
SuperFoo foo = supplier.get();
foo.bar();
}
void bar() { ... }
}
class Foo1 extends SuperFoo {
public static void main(String[] args) {
SuperFoo.create( Foo1::new );
}
}
class Foo2 extends SuperFoo {
public static void main(String[] args) {
SuperFoo.create( Foo2::new );
}
}
class Foo3 extends SuperFoo {
public static void main(String[] args) {
SuperFoo.create( Foo3::new );
}
}
Any common pre-initialization can be moved into the SuperFoo::create method before the supplier is invoked to create the instance of the subclass. For example, opening a connection to a database.
And you still have the individual subclass main methods for instance specific initialization. For example, Foo1::main, Foo2::main and Foo3:main could setup (but not open) connections to different databases.
Based on a comment in Ernest's answer, which gives a link to your comicgetter code, and perusing that code base...
It looks like you want a ServiceLoader
interface FooInterface {
String getName();
void bar();
}
abstract class SuperFoo implements FooInterface {
...
}
public class Foo1 extends SuperFoo {
public String getName() { return "Name1"; }
public void bar() { ... }
}
class Main /* extends nothing, implements nothing! */ {
public static void main(String args[]) {
List<String> names = List.of(args);
boolean all = names.size() == 0;
ServiceLoader<FooInterface> loader = ServiceLoader.load(FooInterface.class);
for (FooInterface foo : loader) {
if (all || names.contains(foo.getName()) {
foo.bar();
}
}
}
}
In a file META-INF/services/your.package.name.FooInterface, you need the lines:
your.package.name.Foo1
your.package.name.Foo2
your.package.name.Foo3
Invoke Main::main with, as arguments, the name (note: not class-name), or names (plural), of the Foo's you want, or with no name to use all Foo's.
Note that class Main has no knowledge of Foo1 or Foo2 or Foo3. The service loader searches for things on the class path that contain META-INF/services/your.package.name.FooInterface. You can add more jar-files later with more FooInterface services for things the main application does not know about (Foo4, Foo5, ...), and these will automatically become supported by the application.