编辑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;
答案 0 :(得分:3)
因为构造函数不像普通方法那样继承。因此,父类中的构造函数不能直接用于子类。
但您仍然可以从子类构造函数中调用父构造函数。
所以解决方法是在子类中创建一个构造函数,然后调用父类中的构造函数。
答案 1 :(得分:2)
因为没有默认构造函数。默认构造函数是没有参数的构造函数。
答案 2 :(得分:2)
来自官方Oracle Java教程:
您不必为您的班级提供任何构造函数,但在执行此操作时必须小心。编译器自动为没有构造函数的任何类提供无参数的默认构造函数。此默认构造函数将调用超类的无参数构造函数。在这种情况下,如果超类没有无参数构造函数,编译器会抱怨,因此您必须验证它是否存在。如果你的类没有显式的超类,那么它有一个隐式的超类Object,它有一个无参数的构造函数。
因此,在您的情况下,为了使您的代码工作,您需要为您的父Date类显式提供一个空构造函数(但要小心,您需要手动提供字段的值,作为空构造函数不会初始化字段&#34; newMonth&#34;,&#34; newDay&#34;和&#34; newYear&#34;)。
答案 3 :(得分:2)
JLS section 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
的调用失败。