如何避免 C# 中的"derived class can have only one base class"问题?



我是C#的新手。我了解到一个派生类只能有一个基类。在我看来,这是C#的一个弱点,但也许我做得不对。我正在寻找";最好的";解决方案,以绕过这一点,同时尊重DRY和clean代码原则。下面我创建了一个例子,我最终从两个类中派生出了这个想法。有两个明显的解决方案:

  1. CColor的成员和方法实现两次CColoredRectangleCColoredTriangle中。但这违反了DRY原则
  2. CColor的成员和方法实现为CShape(或者派生一个CColoredShape类作为其他类的基础)。但是CColor方法在CRectangleCTriangle中是可用的,其中它们不应该存在。这违背了干净代码的思想

接口不能完成任务,因为它们不允许成员。有什么优雅的解决方案吗?提前谢谢。

public abstract class CShape
{
private double x,y;
protected CShape(double x, double y)
{
this.x = x;
this.y = y;
}
public abstract double Area { get; }

public class CRectangle : CShape
{
protected CRectangle(double x, double y) : base(x, y) { }
public override double Area => x * y;
}
public class CTriangle : CShape
{
protected CTriangle(double x, double y) : base(x, y) { }
public override double Area => x * y * 0.5;
}
public class CColor
{
public int R,G,B; //I need members here, so an interface won't work
public void MixColorWith(int r,int g,int b) { /*Code....*/}
}
public class CColoredTriangle : CTriangle, CColor //compiler error CS1721
{
}
public class CColoredRectangle : CTriangle, CColor //compiler error CS1721
{
}
}
我了解到一个派生类只能有一个基类。在我看来,这是C#〔…〕的一个弱点

让我们回顾一下在你看来哪些事情是正确的,以便能够量化这是C#的弱点的说法,同样在你看来。

你假设一个彩色三角形就是一种颜色。这就是继承的意义,它是一种"继承";is-a";关系虽然存在一些不是彩色三角形的颜色,但你可以假设至少有一些颜色是彩色三角形。我们在这里意见一致吗?

因此,我的观点是:不存在一种颜色是彩色三角形。不存在";is-a";这里的关系。你可能能够证明这样一个事实,即彩色三角形";有一个";颜色,在这种情况下,您将向其添加Color属性,但仅限于此。

因此,您的问题不需要钻石(多重)继承。

编辑:还有你假设的另一件事,"我需要这里的成员,所以接口不起作用",从两方面来看都是完全错误的。在C#中,接口可以同时具有属性和方法。

一般来说,大多数专家都说你应该"偏爱组合而非继承">

在这种情况下,这几乎是正确的做法

CColoredTriangle不是CColor,它有一个CColor,因此它应该只是它的一个属性。

考虑到您似乎也希望能够通过对象具有CColor这一事实来引用对象,而不管它们是什么形状,创建IHasColor接口是有意义的

public abstract class CShape
{
private double x,y;
protected CShape(double x, double y)
{
this.x = x;
this.y = y;
}
public abstract double Area { get; }

public class CRectangle : CShape
{
protected CRectangle(double x, double y) : base(x, y) { }
public override double Area => x * y;
}
public class CTriangle : CShape
{
protected CTriangle(double x, double y) : base(x, y) { }
public override double Area => x * y * 0.5;
}
public class CColor
{
public int R,G,B;
public void MixColorWith(int r,int g,int b) { /*Code....*/}
}
public interface IHasColor
{
CColor Color {get; set;}
}
public class CColoredTriangle : CTriangle, IHasColor
{
CColor Color {get; set;}
}
public class CColoredRectangle : CTriangle, IHasColor
{
CColor Color {get; set;}
}
}

相关内容

最新更新