[英]C# derived class and base constructor parameter logic
我有一个基类:
public class Base
{
public Base(X x ,Y y){
this.x = x;
this.y = y;
}
public X x{get;}
public Y y{get;}
}
和一个派生者:
public class Derive : Base
{
public Derive(Z z, Q q) :Base (? ?)
{
}
private void ConstructXY(Z z, Q q)
{
//Advanced logic for creating an X and a Y
if(q.something == 5){
this.x = new X(28);
}
else{
this.x = new X(25);
}
if(this.x.something == 25 && q == 9){
this.y = new Y(1);
}
else{
this.y = new Y(5)
}
}
}
现在,如果没有“高级”逻辑,就无法正确地调用基本构造函数。 我曾经能够从Derive.ctor()调用ConstructXY()并从那里设置x和y,这不再有效,因为我删除了x和y设置器。 我的现实生活场景包含更多逻辑,因此我不愿意创建三元混乱。
如果适合静态方法,则可以调用“高级”逻辑
这是使用C#7中可用的Tuple的方法:
public class Base
{
// This constructor was added to avoid calling twice ConstructXY
public Base((X x, Y y) tuple) :
this (tuple.x, tuple.y)
{
}
public Base(X x, Y y)
{
this.x = x;
this.y = y;
}
public X x { get; }
public Y y { get; }
}
public class Derive : Base
{
public Derive(Z z, Q q) : base(ConstructXY(z, q))
{
}
private static (X x, Y y) ConstructXY(Z z, Q q)
{
X x;
Y y;
//Advanced logic for creating an X and a Y
if (q.something == 5)
{
x = new X(5);
}
else
{
x = new X(25);
}
if (x.something == 25 && q == 9)
{
y = new Y(1);
}
else
{
y = new Y(5)
}
return (x, y);
}
}
如果您不能在基类中更改X
和Y
的访问修饰符,以便子类可以访问它们,那么您将必须遵守合同,将构造函数留在可以设置这些成员的唯一可能的位置。
添加更多逻辑来计算这些值的唯一方法是使用静态方法,例如:
public class Derive : Base
{
public Derive(Z z, Q q)
: base(ConstructX(q), ConstructY(q, z))
{ }
private static X ConstructX(Q q)
{
if (q.something == 5)
return new X(28);
else
return new X(25);
}
private static Y ConstructY(Q q, Z z)
{
if (z.something == 25 && q.something == 9)
return new Y(1);
else
return new Y(5);
}
}
由于这些是单独的方法调用,因此您无法“一次”计算两个值,因此,如果不再次基于Z
和Q
重新进行计算,就无法使Y
的结果取决于X
的结果。
解决此问题的另一种方法是,完全删除Derive
上的public构造函数,并提供一个静态工厂方法:
public class Derive : Base
{
private Derive(X x, Y y)
: base(x, y)
{ }
public static Derive Create(Z z, Q q)
{
// here you can use your original logic to calculate X and Y
X x = …
Y y = …
return new Derive(x, y);
}
}
根据您的计算复杂度,这可能是更好的解决方案。 如果确实需要原始的Z
和Q
值,则只需扩展private构造函数以同时使用它们并存储它们:
private Derive(Z z, Q q, X x, Y y)
: base(x, y)
{
this.Z = z;
this.Q = q;
}
为什么不将您的基类设置器声明为私有:
public class Base
{
public Base(X x ,Y y){
this.x = x;
this.y = y;
}
public X x{get; private set;}
public Y y{get; private set;}
}
这样,您仍然可以在构造函数中设置它们,并且它们将无法在外部设置?
我不太喜欢这种方式,如果可能的话会避免使用,但是您可以在对base
的调用中使用三元语句:
public Derive(Z z, Q q)
: base(new X(xCondition ? 28 : 25), new Y(yCondition ? 1 : 5))
使用静态方法进行转换。 像这样。
public class Derive : Base
{
public Derive(Z z, Q q) :base (ConvertToX(z, q), ConvertToY(z, q))
{
}
private static X ConvertToX(Z z, Q q) {
if(q.something == 5){
return new X(28);
}
return new X(25);
}
private static Y ConvertToY(Z z, Q q) {
// TODO
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.