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.