VB_
VB_

Reputation: 45722

How constructor overloading works

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

Answers (2)

JB Nizet
JB Nizet

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

Alexander Pogrebnyak
Alexander Pogrebnyak

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

Related Questions