也许我说过的问题不是正确的问题,因为我已经知道简短的回答是“你不能”。
我有一个带有重载构造函数的基类,它带有两个参数。
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
运算符。我已尝试在基类virtual
中创建BuildingType,但不能将字段设为虚拟字段。
在这个简单的示例中,默认构造函数仅为某些属性指定默认值。但构建构造函数也可以为构建创建一个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的每个实例化上执行,我必须在所有构造函数中调用。这就是构造链接对我来说听起来更好的原因。
答案 0 :(得分:52)
您的方法不是传统方法,可以解决问题。而不是使更具体的构造函数(具有大量参数的构造函数)调用无参数的构造函数,而是反过来做事 - 使无参数调用另一个调用另一个,提供默认值。这通常导致所有构造函数在每个类中调用一个“主”调用(可能间接地,通过其他类),并且“主”构造函数调用使基本构造函数调用。
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
参数。)
答案 1 :(得分:1)
创建一个私有方法,为所有属性分配默认值,并分别从每个构造函数中调用它们。