【问题标题】:overriding parameterized constructors in sub-classes in java覆盖java子类中的参数化构造函数
【发布时间】:2017-02-03 09:53:24
【问题描述】:

我只是从 Java 开始我的故事,但是我对 Python 有一些 OOP 经验。我有以下类层次结构:

class A {
   public A() {};
   public A(final java.util.Map dict) {};
}

class B extends A {
}

public class Main {
  public static void main() {
     java.util.Map d = new java.util.HashMap();
     B b = new B(d);
  }
}

附加代码导致以下错误:

Main.java:16: error: constructor B in class B cannot be applied to given types;
     B b = new B(d);
           ^
  required: no arguments
  found: Map
  reason: actual and formal argument lists differ in length
1 error

我的期望是,由于所需的构造函数已经在基类中定义,不需要再定义另一个构造函数。为什么我需要为子类定义一个,因为除了调用 super() 之外,它们没有做任何特别的事情?有什么特殊原因,为什么java编译器要我在子类中定义构造函数?

【问题讨论】:

  • 诸如“为什么语言会这样工作”之类的问题只能由语言的设计者来回答,而不是由这个社区来回答。在 Java 中,构造函数不是继承的。这是事实。除此之外的任何事情都是猜测。
  • "有什么特殊原因,为什么java编译器要我在子类中定义构造函数?"您的意思是除了 James Gosling 和 Java 标准委员会认为这种方式更好之外还有其他原因吗?不,没有。
  • @AdrianColomitchi,我想知道 James Gosling 和 Java 标准委员会采用这种设计设计的原因?
  • 旁注:不要使用原始类型。

标签: java oop inheritance constructor constructor-inheritance


【解决方案1】:

在 Java 中 - 当您使用构造函数扩展某个 A 类时,B 子类的构造函数总是必须调用它。如果 A 得到 0 个参数——你不必写任何东西——编译器会自动调用它。如果有更多参数,您必须使用super() 将它们传递给基本构造函数。以下是一些示例:

public class A {
    public A(int something) {

    }
}

public class B extends A {
    public B(int something) {
        super(something);
    }
}

public class C extends A {
    public C() {
        super(999);
    }
}

//--------------------------------------------//

public class A {
    public A() {

    }
}

public class B extends A {
    public B(int something) {
        super();
    }
}

public class C extends A {
    public C(int something) {
    }
}

public class D extends A {
    public D() {
        super();
    }
}

public class E extends A {
    public E() {

    }
}

【讨论】:

    【解决方案2】:

    默认构造函数是在没有定义构造函数时自动创建的。您必须在 B 中添加默认构造函数才能调用 A 的默认构造函数。

    所以您的代码需要以下内容

    class B extends A
    {
        B(){
          super();  // calling super class  default constructor
        }
        B(Map dict) {
            super(dict); // calling super class single parameter(map) constructor
        }
    }
    

    这样

    B b = new B(); //invokes A's Default Constructor
    B b = new B(d); //invokes A's Parameter Consturctor
    

    希望这很清楚

    【讨论】:

      【解决方案3】:

      为什么不继承构造函数?构造函数用于初始化对象,通常在从类继承时,您倾向于使用通用功能,但创建可能会有所不同,所以扩展构造函数还有什么用处,您将只是拥有 super 的副本类,在这种情况下,将所有常用功能放在一个类中并拥有一个包含不同功能的实用程序类会是一种更好的做法。

      【讨论】:

        【解决方案4】:

        如果您不想在 B 类中初始化任何东西,则需要在 B 类中声明参数化构造函数并从中调用 super。

        类似:

        import java.util.*; 
        
        class B extends A
        {
            B(Map dict) {
                 super(dict);
             }
        }
        

        【讨论】:

          【解决方案5】:

          当您实例化一个类时,必须调用该类的构造函数。

          当 Java 类没有构造函数时,编译器会自动生成一个无参数构造函数,它允许您实例化没有参数的类(在您的示例中,它允许 new B())。

          由于您尝试使用参数实例化 B 类,因此您必须声明一个适当的构造函数,该构造函数调用您选择的超类构造函数:

          public B(Map dict) {
              super(dict);
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-01-17
            • 1970-01-01
            • 2021-03-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-02-01
            相关资源
            最近更新 更多