简体   繁体   中英

Java: Why do you need constructors to use objects in a parent class?

Edit 2: By the way guys, my code in the class works and passed all the testers. I'm just trying to wrap my head around constructors. Date d is an object; a product of the constructor of Date, correct? So if IncDate is a Date (that's what extends means, I think), wouldn't it have access to the constructor of Date and therefore be able to create new Date objects and/or use them? Again guys, thanks a lot!

For example: The class I am working on in my Data Structures class looks something like this. This is the constructor of the sub-class:

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;
}

This is the constructor of the parent class:

   public Date(int newMonth, int newDay, int newYear)
{
    month = newMonth;
    day = newDay;
    year = newYear;
}

So here's my question. If the function "extends" basically gives the subclass access to its methods and objects, then in the world do I need to create a new constructor in the sub-class so I can use the Date object that was created in the parent class? It confuses me a lot. If anything, all the IncDate constructor does it inherit the values of the parent class's constructor, but it doesn't inherit the option to use a Date object, as extends basically means "is a", so IncDate is a Date class, so therefore it should have the option to create and use Date objects without making it's own constructor. I'm confused a lot.

TL;DR: If I remove the IncDate constructor, the Date object in the increment method doesn't work. Why?

Thanks guys. You're a big help around here!

Edit: Because people asked, here are the inverseLilian and lilian methods found in the Date class.

    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;

Because constructors are not inherited like normal methods. So the constructor in your parent class, is not directly available to subclasses.

But you can still call the parent constructor from your sub classes constructor.

So the solution is to create a constructor in your sub class, which then call the constructor in the parent class.

It's becuase there is no default constructor. The default constructor is the constructor with no params.

From the official Oracle Java tutorial:

You don't have to provide any constructors for your class, but you must be careful when doing this. The compiler automatically provides a no-argument, default constructor for any class without constructors. This default constructor will call the no-argument constructor of the superclass. In this situation, the compiler will complain if the superclass doesn't have a no-argument constructor so you must verify that it does. If your class has no explicit superclass, then it has an implicit superclass of Object, which does have a no-argument constructor.

So, in your case, to make your code work you need to explicitly provide an empty constructor to your parent Date class (but be careful that you'll need to manually provide values for the fields, as the empty constructor will not initialize fields "newMonth", "newDay" and "newYear").

The JLS section 8.8.9 makes this explicit.

It is a compile-time error if a default constructor is implicitly declared but the superclass does not have an accessible constructor that takes no arguments and has no throws clause.

Let's back up a bit and describe the two different types of constructors - default and defined.

A default constructor is declared implicitly ; that is, if you do not declare your own constructor for the class, Java declares it for you. It only contains a call to super() (as long as it's not Object ):

If the class being declared is the primordial class Object, then the default constructor has an empty body. Otherwise, the default constructor simply invokes the superclass constructor with no arguments.

A defined constructor is one you explicitly declare. Even if it matches the implicit constructor, the very presence of a constructor means that there is no longer a "default" constructor for Java to use.

So, this means that for two classes Parent and Child , their declarations look as thus to Java. Note that these are implicit declarations.

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
    }
}

Now, this is why your code won't work: your parent class doesn't have a default constructor that doesn't throw anything, which is what the implicit call is looking for.

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
    }
}

Your parent class doesn't have a no-arg constructor, so the call to super fails.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM