簡體   English   中英

Java:為什么需要構造函數來使用父類中的對象?

[英]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的“默認”構造函數。

所以,這意味着對於兩個類ParentChild ,它們的聲明看起來就像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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM