Reputation: 45722
How to make Factory.create
to invoke Task.<init>(SubType)
constructor if I can't modify Factory.create
method (can modify only Task
and SubType
classes)?
public class Test {
public static void main(String[] args) {
Factory.create(new SubType());
// OUTPUT:
// task instanceof SubType: true
// callable (PROBLEM: I want SubType constructor to be invoked)
}
public static class SubType implements Callable {
@Override
public Object call() throws Exception {
return null;
}
}
public static class Task {
private Callable callable;
private SubType subType;
public Task(SubType subType) {
System.out.println("Subtype");
this.subType = subType;
}
public Task(Callable callable) {
System.out.println("callable");
this.callable = callable;
}
}
public static class Factory {
// If change method argument type to SubType it will invoke
// Task.<init>(SubType) constructor, but I can't modify it
public static Task create(Callable task) {
System.out.println("task instanceof SubType: " + (task instanceof SubType));
return new Task(task);
}
}
}
Upvotes: 0
Views: 88
Reputation: 692151
The choice of which overloaded method or constructor is invoked is done at compilation time, based on the declared type of the argument. So, even if the actual concrete type of task
is SubType
, its declared type is Callable
, and the second constructor, taking a Callable as argument, will always be invoked.
So, if you want something different to happen when a Task is constructed with a SubType, then you should test the type of the Callable in the Task constructor:
public static class Task {
private Callable callable;
private SubType subType;
public Task(Callable callable) {
if (callable instanceof SubTask) {
System.out.println("Subtype");
this.subType = subType;
}
else {
System.out.println("callable");
this.callable = callable;
}
}
}
Upvotes: 2
Reputation: 45606
Create a public factory static method on Task
class, and make constructors private, or package private
public static class Task {
private Callable callable;
private SubType subType;
private Task(SubType subType) {
System.out.println("Subtype");
this.subType = subType;
}
private Task(Callable callable) {
System.out.println("callable");
this.callable = callable;
}
public static Task create ( final Callable callable )
{
if ( callable instance of SubTask )
{
return new Task( (SubType) callable );
}
return new Task( callable );
}
}
public static class Factory {
// Note that we are now calling Task's factory method
public static Task create(Callable task) {
System.out.println("task instanceof SubType: " + (task instanceof SubType));
return Task.create(task);
}
}
Upvotes: 3