[英]Java: Why do you need constructors to use objects in a parent class?
編輯2:順便說一下,我的班級代碼可以運行並通過所有測試人員。 我只是想繞着構造者。 日期d是一個對象; Date的構造函數的產品,對嗎? 因此,如果IncDate是一個日期(這是擴展的意思,我認為),它是否可以訪問Date的構造函數,因此能夠創建新的Date對象和/或使用它們? 伙計們,非常感謝!
例如:我在我的Data Structures類中工作的類看起來像這樣。 這是子類的構造函數:
public class IncDate extends Date
public IncDate(int newMonth, int newDay, int newYear)
{
super(newMonth, newDay, newYear);
}
public void increment()
{
Date d = inverseLilian(lilian() + 1);
month = d.month;
day = d.day;
year = d.year;
}
這是父類的構造函數:
public Date(int newMonth, int newDay, int newYear)
{
month = newMonth;
day = newDay;
year = newYear;
}
所以這是我的問題。 如果函數“extends”基本上給了子類訪問它的方法和對象,那么在世界上我是否需要在子類中創建一個新的構造函數,以便我可以使用在父類中創建的Date對象? 這讓我很困惑。 如果有的話,所有的IncDate構造函數都會繼承父類的構造函數的值,但它不會繼承使用Date對象的選項,因為extends基本上意味着“是a”,所以IncDate是Date類,因此它應該具有創建和使用Date對象的選項,而無需使用它自己的構造函數。 我很困惑。
TL; DR:如果我刪除了IncDate構造函數,則increment方法中的Date對象不起作用。 為什么?
多謝你們。 你在這附近有很大的幫助!
編輯:因為有人問,這里是Date類中的inverseLilian和lilian方法。
public Date inverseLilian(int lilian)
{
int temp = ((lilian + 139444) * 100) / 3652425;
int days = temp + lilian + 139444 - (temp / 4);
temp = days * 100 / 36525;
if((days * 100) % 36525 == 0)
temp -= 1;
days = days - (temp * 36525 / 100);
int years = temp + 1201;
// account for leap year
int leapDay = 0;
if (years % 4 == 0) leapDay ++;
if (years % 100 == 0) leapDay --;
if (years % 400 == 0) leapDay ++;
if (days > leapDay + 59) days += (2 - leapDay);
int months = (((days + 91) * 100) / 3055);
days = (days + 91) - ((months * 3055) / 100);
months -= 2;
return new Date(months,days,years);
}
public int lilian()
{
// Returns the Lilian Day Number of this date.
// Precondition: This Date is a valid date after 10/14/1582.
//
// Computes the number of days between 1/1/0 and this date as if no calendar
// reforms took place, then subtracts 578,100 so that October 15, 1582 is day 1.
final int subDays = 578100; // number of calculated days from 1/1/0 to 10/14/1582
int numDays = 0;
// Add days in years.
numDays = year * 365;
// Add days in the months.
if (month <= 2)
numDays = numDays + (month - 1) * 31;
else
numDays = numDays + ((month - 1) * 31) - ((4 * (month-1) + 27) / 10);
// Add days in the days.
numDays = numDays + day;
// Take care of leap years.
numDays = numDays + (year / 4) - (year / 100) + (year / 400);
// Handle special case of leap year but not yet leap day.
if (month < 3)
{
if ((year % 4) == 0) numDays = numDays - 1;
if ((year % 100) == 0) numDays = numDays + 1;
if ((year % 400) == 0) numDays = numDays - 1;
}
// Subtract extra days up to 10/14/1582.
numDays = numDays - subDays;
return numDays;
因為構造函數不像普通方法那樣繼承。 因此,父類中的構造函數不能直接用於子類。
但您仍然可以從子類構造函數中調用父構造函數。
所以解決方案是在子類中創建一個構造函數,然后調用父類中的構造函數。
這是因為沒有默認構造函數。 默認構造函數是沒有參數的構造函數。
從官方Oracle Java教程:
您不必為您的類提供任何構造函數,但在執行此操作時必須小心。 編譯器自動為沒有構造函數的任何類提供無參數的默認構造函數。 此默認構造函數將調用超類的無參數構造函數。 在這種情況下,如果超類沒有無參數構造函數,編譯器將會抱怨,因此您必須驗證它是否存在。 如果你的類沒有顯式的超類,那么它有一個隱式的超類Object,它有一個無參數的構造函數。
因此,在您的情況下,為了使您的代碼工作,您需要為您的父Date類顯式提供一個空構造函數(但要小心您需要手動提供字段的值,因為空構造函數不會初始化字段“ newMonth“,”newDay“和”newYear“)。
JLS 第8.8.9節明確說明了這一點。
如果默認構造函數是隱式聲明的,但是超類沒有可訪問的構造函數,該構造函數不帶參數且沒有throws子句,那么這是一個編譯時錯誤。
讓我們稍微回顧一下並描述兩種不同類型的構造函數 - 默認和定義。
默認構造函數是隱式聲明的; 也就是說,如果你沒有為類聲明自己的構造函數,Java會為你聲明它。 它只包含對super()
的調用(只要它不是Object
):
如果聲明的類是原始類Object,則默認構造函數具有空體。 否則,默認構造函數只調用不帶參數的超類構造函數。
定義的構造函數是您明確聲明的構造函數。 即使它與隱式構造函數匹配,構造函數的存在意味着不再使用Java的“默認”構造函數。
所以,這意味着對於兩個類Parent
和Child
,它們的聲明看起來就像Java一樣。 請注意,這些是隱式聲明。
public class Parent {
public Parent() {
super(); // call out to Object's constructor
}
}
public class Child extends Parent {
public Child() {
super(); // call out to Parent's constructor
}
}
現在,這就是為什么你的代碼不起作用的原因:你的父類沒有一個不拋出任何東西的默認構造函數,這就是隱式調用所尋求的。
public class Date {
// Declared, not a default constructor
public Date(int newMonth, int newDay, int newYear) {
month = newMonth;
day = newDay;
year = newYear;
}
}
public class IncDate extends Date
public IncDate() {
super(); // implicit default constructor
}
}
您的父類沒有no-arg構造函數,因此對super
的調用失敗。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.