我有一个抽象类Parent
和一个派生类Child
。我知道我可以通过以下方式在Parent
的构造函数中调用Child
的构造函数:
abstract class Parent
{
protected int i;
protected Parent(int i)
{
this.i = i;
}
}
class Child : Parent
{
public Child(int i) : base(i)
{
}
}
但是,我不想立即将一些参数传递给Parent
构造函数。我想执行一些计算,然后调用Parent
的构造函数,使用这样的计算结果作为输入参数。代码“会看起来像这样:
public class Child : Parent
{
public Child(int i)
{
int calculation = i * 2; // Complicated operation
base(calculation); // This line will break
}
}
第二个片段不是有效的C#代码。有没有办法推迟调用Parent
的构造函数来模仿第二个代码片段中表达的情绪?
答案 0 :(得分:3)
abstract class Parent
{
protected int i;
protected Parent(int i)
{
this.i = i;
}
protected Parent(Func<int> param)
{
i = param();
}
}
class Child : Parent
{
public Child(int i) : base(() => i * 2)
{
}
}
答案 1 :(得分:2)
创建静态方法并使用base(MyStaticMethod(params))
答案 2 :(得分:2)
如果允许您以这种方式在子类中调用 base 构造函数,则可能会在程序中遇到奇怪的问题。意味着您可以将该实例保持在不一致状态,因为您可以使用try-catch来处理某些输入参数错误并绕过构造函数。这不是主意,想象一下,如果你被允许以这种方式创建一个日期。
class MyDate : DateTime
{
public int(int year, int month, int day)
{
try
{
base(-1, -1, -1)
}
catch
{
}
}
}
有趣的是,Java允许使用超级关键字。
答案 3 :(得分:2)
假设您可以直接访问属性,这将采用相同的技巧
abstract class Parent
{
protected int i;
protected Parent()
{
//default constructor
}
}
class Child : Parent
{
public Child(int i)
{
Int calculation = i * 2
base.i = calculation
}
}
但是如果由于对属性的限制访问而无法做到这一点,我个人的偏好是在单独的函数中将计算逻辑外包并调用基类如下:
abstract class Parent
{
protected int i;
protected Parent(int i)
{
this.i = i;
}
}
class Child : Parent
{
public Child(int i) : base(Child.dosomework(i))
{
}
public static int dosomework(int i){
int calculation = i * 2
return calculation
}
}
答案 4 :(得分:1)
构造函数的要点是构造实例,即使其进入有效状态。它应该做到这一点,没有别的。如果您的课程在没有设置i
的情况下可以存在,那么设置i
的行为对其有效性并不重要,因此不属于构造函数。
也许你不想要继承,你想要合成。
class Inner
{
protected readonly int _i;
public Inner(int i)
{
_i = i;
}
}
class Outer
{
protected Inner _inner = null;
public Outer()
{
//Construct
}
public void SetI(int i)
{
_inner = new Inner(i); //Call constructor of Inner
}
}