为啥构造函数在java中不被继承?
Posted
技术标签:
【中文标题】为啥构造函数在java中不被继承?【英文标题】:Why are constructors not inherited in java?为什么构造函数在java中不被继承? 【发布时间】:2013-08-11 10:47:05 【问题描述】:我是java编程语言的初学者,最近研究构造函数不能在java中继承,谁能解释一下为什么?
我已经读过 C++ 的this link
【问题讨论】:
你确实有super()
。
【参考方案1】:
简单来说,构造函数不能被继承,因为在子类中它有不同的名称(子类的名称)。
class A
A();
class B extends A
B();
你只能这样做:
B b = new B(); // and not new A()
相反,方法以“同名”继承并且可以使用。
至于原因: 继承构造函数没有多大意义,因为A类的构造函数意味着创建一个A类型的对象,而B类的构造函数意味着创建一个B类的对象。
您仍然可以在 B 的实现中使用来自 A 的构造函数:
class B extends A
B() super();
【讨论】:
定义“继承”。不继承意味着你可以“使用”它。所以你基本上继承了构造函数? 就我的解释而言,“继承”是指可以使用类B从A类PUBLICLY继承的方法X(即在B类的构造函数作用域之外),例如B b = new B (); b.X();你不能做 B b = new A();所以你不能公开使用“继承的构造函数”,即使你将它们声明为公共,即使在类 B 中也是如此。如果你认为能够在 B 的构造函数中调用构造函数 A 意味着继承,那么继承就是它^^ 现在我知道“为什么”了,但我仍然希望有一些语法糖来消除那些只调用具有相同参数的父构造函数的构造函数。 “构造函数不能被继承,因为在子类中它有不同的名称”——设计选择什么语言!罗特夫。我们想让类难以继承,难以重构,构造函数难以编写。要么就是这样,要么他们就是太喜欢这种自命名构造函数的想法,以至于他们拒绝或从未想过要重命名它们。我们这样做是因为它必须永远作为传统继续下去。 父类构造函数默认从子类构造函数调用。【参考方案2】:你说的是Java语言级别。如果构造函数是继承的,那将不可能将类设为私有。正如我们所知,方法可见性不能降级。 Object
类有一个无参数构造函数,每个类都扩展 Object
,所以在构造函数继承的情况下,每个类都有一个无参数构造函数。这违反了 OO 原则。
字节码级别的情况有所不同。创建对象时,会调用两个运算符:
-
new - 为对象分配内存
invokespecial - 在新分配的内存块上调用构造函数
我们可以修改字节码,以便为子类分配内存并从父类调用构造函数。在这种情况下,我们可以说构造函数是继承的。请注意,如果我们不关闭字节码验证,JVM 将在加载类时抛出异常。我们可以通过添加-noverify
参数来做到这一点。
结论:
-
由于 OO 原则,构造函数不会在语言级别继承
构造函数在字节码级别继承
【讨论】:
【参考方案3】:Reason mentioned in docs of Inheritance
子类从其超类继承所有成员(字段、方法和嵌套类)。构造函数不是成员,所以不被子类继承,但是子类可以调用超类的构造函数。
您可以参考Providing Constructors for Your Classes的文档
【讨论】:
先生,我也读过这个,构造函数是类的特殊成员函数,其名称与类的名称相同,但它们没有任何返回类型。是真的吗? @user2320537 如果你的意思是data type
是指return type
,是的,他们没有return type
。【参考方案4】:
构造函数不是类的成员,只有成员被继承。您不能继承构造函数。也就是说,您不能使用其中一个超类的构造函数来创建子类的实例。
【讨论】:
【参考方案5】: 只能使用new
调用构造函数。它不能作为方法调用。
构造函数名与类名相同。
所以继承实际上是不可能的。 然而,在一个构造函数中,可能会调用其他构造函数。
在同一类中使用this(...)
;
的扩展类使用super(...)
;
例子
class A
A() // Constructor
A(int a) // Constructor
A(boolean c) // Constructor
class B extends A
B()
this(3, 7);
B(int a)
super();
B(String b)
super(7);
B(int a, int c) // Calls super() implicitly
A a = new B(8):
不幸的是,不可能将 A 的构造函数用于布尔值:
B b = new B(true): // ERROR
语言设计可以实现这样的东西:
为基类中的每个公共构造函数生成一个具有相同签名的构造函数,如果这样的构造函数尚未定义。使用相同的参数调用super
。如果有默认构造函数,则调用this()
。
这似乎有点臃肿的代码。并且不仅仅是虚拟方法表中的指针,方法继承/覆盖通过该指针起作用。
【讨论】:
【参考方案6】:我观察到的简单答案,您不能直接在子类中调用或使用父类的构造函数,但可以在子类中直接使用父类的方法。
如果您在子类中有与父类同名的方法,您只需要使用“super”关键字来调用父类方法解决调用歧义。
在子类中“调用”父类构造函数总是需要“super”关键字。所以父类构造函数像子类中的父类方法一样“不直接可用”,所以我们可以说构造函数不能被继承。
【讨论】:
【参考方案7】:-
如果构造函数是在子类中继承的,那么子类将包含一个父类构造函数,这违反了构造函数应与类名同名的约束。
但是,可以使用 super() 从子类构造函数中调用父类构造函数。
演示该概念的示例代码。
class Base
public void Base()
System.out.println("Inside Base class constructor");
class Derived
public void Derived()
super();
System.out.println("Inside Derived class constructor");
class mainClass
public static void main(String args[])
Derived obj = new Derived();
Output:
Inside Base class constructor
Inside Derived class constructor
【讨论】:
【参考方案8】:不,构造函数不会被继承到子类,即使它是一个非静态成员,它也不会被继承到子类,因为构造函数不会被加载到对象内部,它用于创建对象。构造函数就像一个非静态初始化器
【讨论】:
【参考方案9】:只有字段、方法和嵌套类是任何类的成员,而不是构造函数。子类从其超类继承所有成员,例如(字段、方法和嵌套类)。构造函数不是成员,所以不被子类继承,但是子类可以调用超类的构造函数。
【讨论】:
【参考方案10】:如果有任何理由以概念方式使用某个功能,则通常可以规避句法限制。有了这个,我相信,不支持构造函数继承的真正原因不是由于语法限制,而是由于语义。
从概念上讲,继承提供了一种获取(或继承)行为的机制,并且很可能无需编写任何代码,因为它的目的是提供代码重用。对于子类,没有必要继承其父类的初始化行为。毕竟,当外部调用者可以在不知道谁(在父链中)实际实现它的情况下使用它时,继承的行为找到了它的最佳用途。如您所见,调用者几乎不知道如何通过其子类初始化父类,没有明显的理由支持(父类的)构造函数的继承。
【讨论】:
【参考方案11】:你不能继承构造函数,但你可以继承构造函数中的初始化值,比如
class test1
int a,b;
test1()
a = 100;
b = 20;
class test2 extends test1
test2()
// do something
class test
public static void main(String[] args)
test2 t = new test2();
int a = t.a;
int b = t.b;
System.out.println(a+b);
【讨论】:
【参考方案12】:如米哈伊尔所说,否;构造函数不会被继承。
您不能将构造函数从 superclass
继承到您的 subclass
。但是,当在 java 中使用“new”运算符实例化一个对象时,该对象会继承它的所有构造函数superclass(parent)
,甚至包括抽象类中的构造函数(因为它们也是超类)。
【讨论】:
以上是关于为啥构造函数在java中不被继承?的主要内容,如果未能解决你的问题,请参考以下文章