【问题标题】:How constructor overloading works构造函数重载的工作原理
【发布时间】:2015-05-26 16:49:08
【问题描述】:

如果我无法修改Factory.create 方法(只能修改TaskSubType 类),如何使Factory.create 调用Task.<init>(SubType) 构造函数?

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);
        }
    }
}

【问题讨论】:

    标签: java constructor-overloading


    【解决方案1】:

    Task类上创建一个公共工厂静态方法,并使构造函数私有,或者包私有

    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);
        }
    }
    

    【讨论】:

      【解决方案2】:

      根据参数的声明类型,在编译时选择调用哪个重载方法或构造函数。因此,即使task 的实际具体 类型是SubType,它的声明 类型是Callable,而第二个构造函数以一个Callable 作为参数,将始终被调用。

      因此,如果您希望在使用 SubType 构造 Task 时发生不同的事情,那么您应该在 Task 构造函数中测试 Callable 的类型:

       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;
              }
          }
      }
      

      【讨论】:

      • 请注意,这种类型检查是often considered bad practice。 Task 可以用 Callable 的子类型来构造应该是件好事。你为什么要改变它?
      • @markspace 因为那是 OP 想要的,他不能改变 Factory 的实现,从而重载 Factory.create() 方法。
      • 是的,我意识到了。 (实际上,我很难解析 OP 想说的话。)我只是让 OP 知道他想要做什么可能是不好的做法。我想了解什么是目标,他要求做什么似乎值得怀疑。
      • 没问题。这可能确实是一个 XY 问题。
      • @JBNizet 感谢您的回答!我只是想修改一个开源库。所以对Factory.create的改动会导致太多改动。您的解决方案不是那么糟糕的做法(库已经使用它),但是Task 类还有许多其他字段,这使得情况变得更糟。所以,我倾向于以@`AlexanderPogrebnyak 的方式做事
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-18
      相关资源
      最近更新 更多