C#派生类和基构造函数参数逻辑
我有一个基本类:C#派生类和基构造函数参数逻辑,c#,oop,inheritance,C#,Oop,Inheritance,我有一个基本类: 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
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)
}
}
}
现在,如果没有“高级”逻辑,我无法正确地调用基本构造函数。我曾经能够从派生.ctor()调用ConstructXY(),并从那里设置x和y,这不再有效,因为我删除了x和y设置器。我的现实生活场景包含了更多的逻辑,因此我不愿意制造三元混乱。为什么不将基类设置器声明为私有:
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;}
}
这样,您仍然可以在构造函数中设置它们,并且它们不可以在外部设置?为什么不将基类设置器声明为私有的:
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))
我真的不喜欢这样做,如果可能的话,我会避免这样做,但是您可以在对
base
的调用中使用三元语句:
public Derive(Z z, Q q)
: base(new X(xCondition ? 28 : 25), new Y(yCondition ? 1 : 5))
如果“高级”逻辑适合于静态方法,则可以调用它
下面是一种使用C#7中提供的元组的方法:
如果“高级”逻辑适合于静态方法,则可以调用它
下面是一种使用C#7中提供的元组的方法:
如果无法更改基类中
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);
}
}
由于这些是单独的方法调用,您无法“同时”计算这两个值,因此您无法使Y
的结果取决于X
的结果,而不重新基于Z
和Q
进行计算
解决此问题的另一种方法是完全删除derivate
上的公共构造函数,并提供一个静态工厂方法:
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 Derive(Z z, Q q, X x, Y y)
: base(x, y)
{
this.Z = z;
this.Q = q;
}
如果无法更改基类中
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);
}
}
由于这些是单独的方法调用,您无法“同时”计算这两个值,因此您无法使Y
的结果取决于X
的结果,而不重新基于Z
和Q
进行计算
解决此问题的另一种方法是完全删除derivate
上的公共构造函数,并提供一个静态工厂方法:
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 Derive(Z z, Q q, X x, Y y)
: base(x, y)
{
this.Z = z;
this.Q = q;
}
使用静态方法进行转换。像这样
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
}
}
使用静态方法进行转换。像这样
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
}
}
该构造函数应该读取
公共派生(zz,qq):Base(?)
,还是公共派生(zz,qq):Base(?)
?C的哪个版本?我想知道是否可以用C#7中的元组做一些聪明的事情。@TimothyGroote它应该是based是构造函数应该读公共派生(Z Z,Q Q Q):Base(?)
,还是公共派生(Z Z,Q Q):Base(?)
?什么版本的C#?我想知道是否可以用C#7中的元组做一些聪明的事情。@TimothyGroote它应该是basepublic X{get;}
在构造过程中才可以设置。这只是一个小小的简写。public X{get;}
仅在构建期间可设置。这只是一个小小的简化。请注意,这需要更改基类以接受X
和Y
作为单个参数。可能无法更改基类。如果您只想在派生类中访问新构造函数,则可以将其设置为受保护的。在C#7之前,您可能也可以做类似的事情,只需传入一个元组
,注意,这需要更改基类,将X
和Y
作为单个参数。可能无法更改基类。如果您只想在派生类中访问新构造函数,则可以将其设置为受保护的。你也可以在C#7之前做类似的事情,只需传入一个元组
OP,问题中提到他们“不愿意制造三元混乱”——不过,你可以简单地将逻辑移到静态方法,以避免其他答案中所示的“混乱”。@poke我在阅读时不知何故忽略了这一点,然而,这是一个可行的选择,因为其他答案涵盖了将其移到静态方法,所以我不会编辑我的答案并保持原样。是的,没关系:)OP在问题中提到他们“不愿意制造三元混乱”——不过,您可以简单地将逻辑移到静态方法,以避免其他答案中显示的这种“混乱”。@poke我在阅读时不知何故忽略了这一点,但是,这是一个可行的选择,因为其他答案涵盖了将其移到静态方法,所以我不会编辑我的答案并保持原样。是的,这很好:)