簡體   English   中英

如何讓重載的構造函數調用默認構造函數以及基本構造函數的重載?

[英]How can I have an overloaded constructor call both the default constructor as well as an overload of the base constructor?

也許我說過的問題不是正確的問題,因為我已經知道簡短的回答是“你不能”。

情況

我有一個帶有重載構造函數的基類,它帶有兩個參數。

class Building
{
    public BuildingType BuildingType { get; protected set; }
    public string Address { get; set; }
    public decimal Price { get; set; }

    public Building()
    {
        BuildingType = BuildingType.General;
        Address = "Unknown";
    }

    public Building(string address, decimal price)
        : this()
    {
        Address = address;
        Price = price;
    }
}

該課程正在使用枚舉

enum BuildingType { None, General, Office, Apartment }

現在我想創建一個子類Office,它也有一個重載的構造函數。 這個子類添加了另一個屬性(公司)。 在此類中,BuildingType屬性當然應設置為Office。 這是代碼。

class Office : Building
{
    public string Company { get; set; }

    public Office()
    {
        BuildingType = BuildingType.Office;
    }

    public Office(string address, decimal price, string company)
        : base(address, price)
    {
        Company = company;
        // BuildingType = BuildingType.Office; // Don't wanna repeat statement
    }
}

我想要什么,為什么

我希望Office類的第二個構造函數執行base(address, price)構造函數以及Office類的默認構造函數。 我想調用base(address, price)構造函數,所以我不必重復分配基類的所有屬性。 我想調用Office類的默認構造函數,因為它將BuildingType屬性設置為BuildingType.Office。

現在我知道我不能使用這樣的東西。

public Office(string address, decimal price, string company)
    : base(address, price) this()

難道我做錯了什么?

我想知道我的設計是否有問題讓我想要同時調用base(地址,價格)和this()。 也許我不應該在構造函數中設置BuildingType而在其他地方? 我試圖為此引入一個字段。

    public BuildingType BuildingType = BuildingType.General;

但后來我不能在子課上做同樣的事。 我將隱藏基類中的BuildingType字段,因此我必須在子類中使用new運算符。 我已經嘗試在基類中創建BuildingType virtual ,但是不能將字段設為虛擬。

在基礎構造函數中創建一些東西

在這個簡單的示例中,默認構造函數僅為某些屬性分配默認值。 但構建構造函數也可以為構建創建一個Foundation,而Office默認構造函數可能會創建一個......(想不出什么,但是你明白了)。 那么你仍然想要執行兩個默認構造函數。

我在這里想錯了方向嗎?


更新

根據Jon Skeet的回答和評論,這是我的新代碼。 我已經將構造函數鏈接從最不具體到最具體。 我還將BuildingType添加到Building類的構造函數中,使該構造函數受到保護,並使屬性setter成為私有。

enum BuildingType { None, General, Office, Apartment }

class Building
{
    private const string DefaultAddress = "Unknown";

    public BuildingType BuildingType { get; private set; }
    public string Address { get; set; }
    public decimal Price { get; set; }

    #region Optional public constructors
    // Only needed if code other than subclass must 
    // be able to create a Building instance.
    // But in that case, the class itself can be abstract
    public Building() : this(DefaultAddress, 0m)
    {}

    public Building(string address, decimal price)
        : this(BuildingType.General, address, price) 
    {}
    #endregion

    protected Building(BuildingType buildingType)
        : this(buildingType, DefaultAddress, 0m) 
    {}

    protected Building(BuildingType buildingType,
        string address, decimal price)
    {
        BuildingType = buildingType;
        Address = address;
        Price = price;
    }
}

class Office : Building
{
    public string Company { get; set; }

    public Office() : this("Unknown Office", 0m, null) 
    {}

    public Office(string address, decimal price, string company)
        : base(BuildingType.Office, address, price)
    {
        Company = company;
    }
}

您(Jon Skeet或其他人)可以對此修訂版的代碼發表評論嗎?

未解決的一個(次要)問題是Office類的默認構造函數仍需要提供默認地址(上面代碼中的"Unknown Office" )。 如果沒有指定地址,我仍然希望讓基類的構造函數決定地址。 所以這段代碼仍然沒有完全符合我的要求。

我可以通過在派生類中不使用構造函數鏈來解決這個問題,但是相反,它的每個構造函數都直接調用基礎構造函數。 這意味着我要將Office類的默認構造函數更改為

public Office() : base(BuildingType.Office)

這適用於這個簡單的例子,但如果有一些方法我想在Office的每個實例化上執行,我必須在所有構造函數中調用。 這就是構造鏈接對我來說聽起來更好的原因。

你的方法不是傳統方法,它可以解決問題。 而不是使更具體的構造函數(具有大量參數的構造函數)調用無參數的構造函數,而是反過來做事 - 使無參數調用另一個調用另一個,提供默認值。 這通常導致所有構造函數在每個類中調用一個“主”(可能是間接的,通過其他),並且“主”構造函數調用進行基本構造函數調用。

class Office : Building
{
    public string Company { get; set; }

    public Office() : this(null, 0m, null)
    {
    }

    public Office(string address, decimal price, string company)
        : base(address, price)
    {
        Company = company;
        BuildingType = BuildingType.Office; // Don't wanna repeat statement
    }
}

......和基類相同:

class Building
{
    public BuildingType BuildingType { get; protected set; }
    public string Address { get; set; }
    public decimal Price { get; set; }

    public Building() : this("Unknown", 0m)
    {
    }

    public Building(string address, decimal price)
    {
        BuildingType = BuildingType.General;
        Address = address;
        Price = price;
    }
}

(我會認真考慮使Building構造函數包含一個BuildingType參數。)

創建一個私有方法,為所有屬性分配默認值,並分別從每個構造函數中調用它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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