【问题标题】:How to override a method depending on a constructor?如何根据构造函数覆盖方法?
【发布时间】:2016-02-27 13:15:34
【问题描述】:

好的,所以我不确定这个问题是否已经存在,因为我不知道如何格式化它,但问题是:相同的方法能否根据构造函数产生不同的结果? (如果我重复这个问题或者这是一个愚蠢的问题,我深表歉意。)

例如,假设我有一个接口MyInterface 和函数public void foo();。假设我们有课:

public class MyClass implements MyInterface {
    public MyClass() {
        // I want foo() to print "Empty constructor" with sysout.
    }

    public MyClass(int x) {
        // I want foo() to print "Constructor with int" with sysout.
    }
}

所以现在,如果创建两个引用MyClass mc1 = new MyClass();MyClass mc2 = new MyClass(5);,然后调用mc1.foo();mc2.foo();,结果应该是:

空构造函数。

带 int 的构造函数。

我尝试在构造函数中使用new MyInterface { @Override public void foo() { ... } },但似乎不起作用。

【问题讨论】:

  • 所以你想要不同的方法?保护变量?两个不同的类
  • 你这样做是为了好玩吗?有什么意义?
  • 简短回答是,但是您需要编写代码,例如,您可以使用实例字段private Integer value;,在您的public MyClass(int x) 构造函数中,您可以将x 的值分配给value; value = x。然后在foo中,会测试value看是否是nullif (value == null),当valuenull时,打印Empty constructor.,不是时,打印Constructor with int.;举个例子
  • @MadProgrammer,正如我提到的一个保护变量。非常丑陋,我看不出有什么真正的原因,但谁知道呢,我可能错了。
  • 所以你想要不同的行为取决于你调用什么来创建一个对象。这真的听起来你想要两个不同的类都实现接口。

标签: java methods constructor interface overriding


【解决方案1】:

是的,这是多个构造函数旨在允许的 - 通过对象创建进行变化。

public class MyClass implements MyInterface {
    private final String message;
    public MyClass() {
        message = "Empty constructor";
    }

    public MyClass(int x) {
        message = "Constructor with int";
    }

    @Override
    public void foo() {
        System.out.println(message);
    }
}

它甚至是线程安全的。

这里要注意的是方法的实现是完全一样的,变种在构造函数中。根据调用者想要发生的事情,构造函数的调用方式也不同。

【讨论】:

    【解决方案2】:

    回答这个问题:据我所知。或者至少不是直接的,您可以开始读取字节码并在运行时对其进行更改,使其适应——同样,答案是否定的。

    现在奇怪的部分是overridedepending on constructor。不在overriding的范围内。

    根据Class 的状态做不同事情的方法并不太奇怪。但是,我从未听说过如何使类实例化的方法独一无二。话虽如此,这是一个相当丑陋的解决方案。

    public class Test
    {
        private final boolean intConstructorUsed;
    
        public Test () {
            intConstructorUsed = false;
        }
    
        public Test (int x) {
            intConstructorUsed = true;
        }
    
        public void foo () {
            if (intConstructorUsed == true) {
                // do this
            } else {
                // do that
            }
        }
    }
    

    foo 方法并不那么很奇怪。奇怪的是,您基本上必须对 foo 进行不同的实现,具体取决于哪个构造函数,您确定您不希望后面有一个 abstract class,除了您覆盖的一个 abstract void foo () 之外的所有共享方法?当然,这些类看起来几乎相同,但它们并不相同,因为它们不共享 foo ()

    【讨论】:

      【解决方案3】:

      是的。存储变量并在 foo 方法中检查它。

      public class MyClass implements MyInterface {
          private int x;
          public MyClass() {
              // I want foo() to print "Empty constructor" with sysout.
          }
      
          public MyClass(int x) {
              // I want foo() to print "Constructor with int" with sysout.
              this.x = x;
          }
      
          public void foo(){
             if(x > 0)
                System.out.println("Constructor with int");
             else
                System.out.println("Empty constructor");
          }
      }
      

      【讨论】:

      • 所以如果我使用new MyClass(-10),它将打印Constructor with int
      • 如果用户使用<= 0 实例化类,这将不起作用。我建议使用某种Object,例如Integer,只需检查null
      • 你可以存储一个布尔值来指示它是否使用了该构造函数。或者您可以将 int 设为 Integer,而不是检查是否大于零,而是检查它是否为空。默认构造函数为 null。
      • 这也可以工作,并且是最优雅的,也可以制作boolean final
      • @Emz 使用另一个 (boolean) 变量和 Integer 存储值有什么区别?您可以制作 x final 并最终得到相同的结果,只需一个变量
      猜你喜欢
      • 2014-04-11
      • 2016-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-01
      • 2014-06-09
      相关资源
      最近更新 更多