如何在子类中继承超类的构造函数

42

如何从父类继承构造函数到子类?

6个回答

50

构造函数不会被继承,你必须在子类中创建一个新的、参数类型相同的构造函数,并将其映射到超类中与之匹配的构造函数。

以下是演示如何操作的示例:

class Foo {
    Foo(String str) { }
}

class Bar extends Foo {
    Bar(String str) {
        // Here I am explicitly calling the superclass 
        // constructor - since constructors are not inherited
        // you must chain them like this.
        super(str);
    }
}

1
即使作为一个非n00b级别的Java程序员,这对我来说仍然不清楚。你能否澄清一下? - Matt Ball
@熊会吃掉你:如果父类有这样的构造函数:public Class(String arg1) { /* 在此实现 */ },那么子类需要这样一个构造函数:public Subclass(String arg1) { super(arg1); } - Powerlord
这听起来像是一种花哨的方式,即“在子类构造函数中使用super”。我不知道Java中构造函数原型是什么。 - Matt Ball
我认为安德鲁所说的“构造函数原型”,指的是构造函数的签名。然而,答案并不一定正确(或者至少不是很清楚)-- 您不必使用相同的签名声明构造函数,这也没有什么意义,因为客户端代码必须引用新的子类。如果您想调用底层构造函数,用户只需调用super(/* parameter list */),并为参数提供它所需的任何值即可。(至少这就是我在下面的答案中试图表达的观点...) - MCory
在Eclipse中如何自动完成这个操作?当您创建一个新类时,Eclipse可以自动为您编写超级构造函数定义。但是,如果您已经创建了该类并忘记勾选告诉Eclipse执行此操作的框,那么有没有其他方法呢? - trusktr

15

超类构造函数不能在扩展类中继承。虽然可以在扩展类构造函数中使用super()作为第一条语句来调用它。


是的...或者你可以调用任何你想要使用的超类构造函数变体(它可能没有参数,就像@GoodManish所说的那样,或者它可能有更多)。还有一些情况,在这些情况下,编译器会在执行任何一个构造函数的其余部分之前显式地调用super(); - hotshot309

7

默认构造函数是公共的,没有参数(无论声明还是隐含)。默认情况下会被继承。你可以尝试以下代码作为示例:

public class CtorTest {
    public static void main(String[] args) {
        final Sub sub = new Sub();
        System.err.println("Finished.");
    }

    private static class Base {
        public Base() {
            System.err.println("In Base ctor");
        }
    }

    private static class Sub extends Base {
        public Sub() {
            System.err.println("In Sub ctor");
        }
    }
}

如果您想显式调用超类的构造函数,需要像这样操作:
public class Ctor2Test {
    public static void main(String[] args) {
        final Sub sub = new Sub();
        System.err.println("Finished.");
    }

    private static class Base {
        public Base() {
            System.err.println("In Base ctor");
        }

        public Base(final String toPrint) {
            System.err.println("In Base ctor.  To Print: " + toPrint);
        }
    }

    private static class Sub extends Base {
        public Sub() {
            super("Hello World!");
            System.err.println("In Sub ctor");
        }
    }
}

唯一的注意点是,super()调用必须放在构造函数的第一行,否则编译器会抛出错误。

3
默认构造函数实际上并没有被"继承"。如果在超类中存在一个公共的无参构造函数(也称为默认构造函数),并且在子类中没有显式定义该构造函数,同时子类也没有显式定义任何重载构造函数(即带有参数的构造函数),那么编译器将自动在子类中插入一个公共的无参构造函数,其中仅包含super();。这会调用超类的默认构造函数。 - hotshot309

4

阅读关于super关键字的内容(向下滚动到子类构造函数)。如果我理解你的问题,你可能想调用一个超类构造函数?

值得注意的是,如果您未显式调用超类构造函数,Java编译器会自动插入对超类的无参构造函数的调用。


1

假设你有

/**
 * 
 */
public KKSSocket(final KKSApp app, final String name) {
    this.app = app;
    this.name = name;
    ...
}

那么一个名为KKSUDPSocket的子类,继承自KKSSocket,可以有:

/**
 * @param app
 * @param path
 * @param remoteAddr
 */
public KKSUDPSocket(KKSApp app, String path, KKSAddress remoteAddr) {
    super(app, path, remoteAddr);
}

并且

/**
 * @param app
 * @param path
 */
public KKSUDPSocket(KKSApp app, String path) {
    super(app, path);
}

你只需将参数通过构造函数链传递,就像调用超类的方法一样,但使用super(...)来引用超类构造函数并传入给定的参数。

1

你继承的是类属性,而不是类构造函数。具体如下:

如果父类中没有添加构造函数,则编译器会自动添加一个无参构造函数。当创建子类的新实例时,隐式调用此默认构造函数。此时,子类可以有也可以没有构造函数,都可以。

如果父类中提供了构造函数,则编译器会检查它是无参构造函数还是带参数的构造函数。

如果是无参构造函数,则编译器将为任何子类实例化调用它。同样,子类可以有也可以没有构造函数,都可以。

如果父类中有一个或多个带参数的构造函数,并且没有无参构造函数,则子类必须至少有一个构造函数,在其中通过super(parent_contractor params)进行对父类构造函数的隐式调用。

这样可以确保继承的类属性始终被实例化。


编译器将在任何子类实例化时调用它。似乎上面的意思是,如果您的子类具有无参构造函数,则必须显式调用super()。 - Vlad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接