我有兩個抽象類,一個繼承自另一個。在 Child 抽象類中,除了類的宣告之外,我沒有任何代碼。在父抽象類中,我有一個私有的 int 質量和一個接收 int 的建構式。由于某種原因,沒有任何代碼,編譯器會給我編譯時錯誤。當它試圖呼叫父類建構式時,java 只給了他的孩子默認的一個。
我的問題是:為什么沒有任何代碼編譯器會給我這個錯誤。
uj5u.com熱心網友回復:
從你寫的情況來看,情況似乎是這樣的:
// in a file A.java
public abstract class A {
private int quality;
public A(int quality) {
this.quality = quality;
}
}
// in another file B.java
public abstract class B extends A {
}
編譯器將編譯這些類,因為當它生成 .class 檔案時,它生成的類必須是功能性的。您說“沒有任何代碼”,但上面是代碼。這不是您在任何地方使用的代碼。
但是,javac 生成的 .class 檔案可以從另一個源鏈接到。編譯器不知道,因此它確保代碼編譯或生成錯誤。
在您的情況下,如果您定義建構式,則必須顯式呼叫父建構式或假定默認建構式。
所以你的 B 類沒有定義建構式。默認建構式是不可見的。這個默認建構式只能嘗試呼叫它的超級建構式。具體來說,它呼叫父級默認建構式。除了建構式不存在。
生成的建構式不能呼叫帶有 1 個引數的建構式,因為它不知道為該引數輸入什么。因此,基本上,如果您有一個建構式引數,您的子類需要提供該引數,或者您在父級別提供一個默認建構式。
所以這兩個作業:
public abstract class A {
private int quality;
public A(int quality) {
this.quality = quality;
}
}
public abstract class B extends A {
public B() {
super(0);
}
}
要么
public abstract class A {
private int quality;
public A() {
this(0);
}
public A(int quality) {
this.quality = quality;
}
}
public abstract class B extends A {
}
在第一種情況下,子類顯式呼叫父建構式。在第二個中,父母負責知道如何處理該值。
可能在您的情況下(如果您希望另一個類擴展 B 并提供實作),您可能希望這樣做:
public abstract class A {
private int quality;
public A(int quality) {
this.quality = quality;
}
}
public abstract class B extends A {
public B(int quality) {
super(quality);
}
}
然后,當您使用非抽象(具體)類擴展此類時,它可以提供價值鏈。
最后再一次,因為我覺得這是您問題背后的想法:
僅僅因為代碼沒有在專案的其余部分中使用并不意味著編譯器沒有嘗試創建可用的類。因為您可以從專案中獲取任何類檔案并將其復制到其他地方并使用它。所以編譯器提供的內容必須是正確的,否則會引發錯誤。
uj5u.com熱心網友回復:
你有這兩個類定義(或等效的東西)。
abstract class Parent {
private int quality;
Parent(int quality) {
this.quality = quality;
}
}
abstract class Child extends Parent {
}
讓我們先看看Parent' 的建構式。只有一個,它需要呼叫者提供一個quality值。您明確不提供允許您保留quality未指定的建構式。
現在你有一個Child擴展類Parent。不要指定任何建構式,因此 Java 的默認值適用,以靜默地創建一個愚蠢的無引數建構式。
該類Child擴展了它的Parent類,這意味著每個Child實體都具有 的所有屬性Parent,包括quality. 但是在構造 時Child,您沒有提供一種方法來指定要使用的值quality。
在 Java 繼承系統中,建構式必須始終從初始化實體的父類方面開始,通過呼叫父建構式,使用super(...)語法。如果您不自己撰寫該呼叫,它會被靜默插入到您的建構式中。
撰寫顯式建構式而不是依賴一些愚蠢的自動操作是一種很好的做法,并且通常需要撰寫。在繼承的情況下,建構式應該以super(...)呼叫開始,指定如何初始化要創建的實體的父方面,在您的情況下quality為父建構式提供值。
因此,根據您的要求,解決方案可能是
abstract class Child extends Parent {
Child() {
super(42); // All Child instances get a constant quality=42
}
}
要么
abstract class Child extends Parent {
// When cinstructing a Child instance,
// an explicit quality value must be supplied.
Child(int quality) {
super(quality);
}
}
應用所有內置 Java 自動代碼規則后,您的原始版本相當于
// Auto: If you don't specify a parent class, it's java.lang.Object
abstract class Parent extends Object {
private int quality;
Parent(int quality) {
super(); // Auto: calls the `Object()` constructor to initialize
// aspects that every Java instance needs
this.quality = quality;
}
}
abstract class Child extends Parent {
// Auto: no constructor supplied in source, so a dumb one gets generated
Child() {
super(); // Auto: calls the parent's no-args constructor
// But there is no such constructor, hence compile error.
}
}
uj5u.com熱心網友回復:
將建構式添加到子類并super()在建構式內部使用。
例子:
abstract class Parent{
private int x;
Parent(int x){
this.x = x;
}
}
abstract class Child extends Parent{
Child(int y){
super(y);
}
}
現在沒有編譯錯誤:)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/428613.html
