Reputation: 5759
I have a parent class in java with some behavior defined
public class ParentClass {
public ParentClass() {
//Do some instantiation
}
public void doWork() {
//Do some behavior defined by the parent class
}
}
Now I have some other class in my project that uses this. Let's say it is used in main
public class Main {
public static void main(String [] args) {
ParentClass parent = new ParentClass();
parent.doWork();
}
}
Now let's say that my project is setup as a Library for other developers to use. I want them to be able to extend ParentClass and override the doWork() method to their liking. If the developer can not change the Main class, how can I assure that ChildClass is instantiated in main() instead of ParentClass?
Example of ChildClass
public class ChildClass extends ParentClass {
public ChildClass() {
super();
//Do some more instantiation
}
@Override
public void doWork() {
super.doWork();
//Do some more behavior in child class
}
}
Upvotes: 3
Views: 1558
Reputation: 311002
A library shouldn't have a main class in the first place. Make up your main what it is you're shipping: an application or a library.
Or maybe what you're looking for is the Abstract Factory pattern.
Upvotes: 1
Reputation: 82461
You could use java.util.ServiceLoader
to load a instance of ParentClass
, but there are some things you need to consider:
ParentClass
, filename META-INF/services/ParentClass
(replace ParentClass
with the fully qualified name of the class implemented). For every class implementing ParentClass
you need to add a line to this file containing the fully qualified name of the implementing class.public
no-argument constructor.package mypackage;
// used interface here, since in this case there's no reason to use
// a class
// you could use a class here too
public interface ParentClass {
public void doWork();
}
public class Main {
public static void main(String [] args) {
// execute doWork of every ParentClass provided
for (ParentClass parent : ServiceLoader.load(mypackage.ParentClass.class)) {
parent.doWork();
}
}
}
ParentClass
package mypackage2;
public class ImplementingClass implements ParentClass {
@Override
public void doWork() {
// Custom implementation
System.out.println("Hello world");
}
}
mypackage2.ImplementingClass
Then you only need to add the other jar to your classpath when executing your program.
Upvotes: 1
Reputation: 449
This depends on what you want to achieve, if your library is intended to be used by another 3rd party then most probably your main method would be irrelevant as your JAR package would be bundled in his own JAR, which would only allow for a single main class; his.
This approach may require you to have some trigger to initiate your class (engine?), again, depending on how you intend clients to use your APIs.
Furthermore, you can check the Template Method design pattern as it may be useful for your case, in essence, it allows you to settle the bold lines of your algorithm and define which parts you would like clients to redefine/extend.
Upvotes: 2
Reputation: 48682
No need to rely on your provided main method. If they can extend your class they can create an object of their extending class in their own main method.
Upvotes: 0
Reputation: 72864
Well there seems to be many ways of doing this. One simple way is to have the client pass the name of the child class as a system property. The main
can access the class name using System.getProperty("prop.name")
.
Another way is to use the Services API to look for implementing classes. See https://docs.oracle.com/javase/tutorial/ext/basics/spi.html#the-serviceloader-class.
Having said this, what you described is weird because the client code itself is usually supposed to have its own main
.
Upvotes: 1