C# base inheritance
本文关键字:inheritance base | 更新日期: 2023-09-27 18:36:59
这个问题一直困扰着我,我现在写了 4 个包装器。我确定我做错了,需要弄清楚我的理解在哪里分支。
假设我使用 Rectangle 类来表示金属条。(这比动物效果更好)
所以说基类被称为"Bar"。
private class Bar
{
internal Rectangle Area;
}
所以。现在我们做一个矩形,比如说 300 个单位乘以 10 个单位。
private Bar CreateBar()
{
Bar1 = new Bar1();
Bar1.Area = new Rectangle(new Point(0,0), new Size(300,10));
return Bar1;
}
太棒了,所以我们有一个基础栏。
现在假设我们想让这个棒材有一种材料——比如钢。所以。
private class SteelBar : Bar
{
string Material;
}
所以如果我这样做了
。。。private SteelBar CreateSteelBar()
{
SteelBar SteelB = new SteelB();
Bar B = CreateBar();
SteelB = B;
SteelB.Material = "Steel";
return SteelB;
}
从我从中得到的,如果我称之为CreateSteelBar,它会创建一个称为CreateBar的钢筋。所以我最终得到了一个带有 300 x 10 矩形的钢筋,以及一个空或空的材料字符串。然后我将材料设置为钢。
当我在我的程序中尝试类似的东西时,它一直告诉我不能从较低的下级隐式创建一个更高的上级类。考虑到我看到的所有动物例子的遗传,我会认为这就是遗传存在的原因,但我希望有人能澄清我。
另外,我确信我可以打电话给SteelBar = CreateBar();
但我在这里做了很长的路。
而不是使用方法 ( CreateBar
),您将使用构造函数:
public Bar()
{
this.Area = new Rectangle(new Point(0,0), new Size(300,10));
}
然后,在 SteelBar 中,您将调用基类构造函数:
public SteelBar()
{
this.Material = "Steel";
}
基类构造函数将首先出现,因此您的区域已经设置好。 不过,您可以明确说明这一点,并在代码中显示它:
public SteelBar()
: base()
{
this.Material = "Steel";
}
但是,这通常仅在您希望具有接受参数的特定构造函数时才使用。
有关详细信息,请参阅 C# 编程指南中的构造函数。
这是你的问题:
Bar B = CreateBar();
SteelB = B;
B
是任何类型的酒吧。您正在尝试将其分配给SteelBar
。这是错误的,它可以是任何类型的酒吧(铜,木材,Tiki,...您可以这样做:
SteelBar sb = new SteelBar();
Bar b = sb;
因为SteelBar
是某种酒吧,但反之则不然。
另外,我确定我可以调用 SteelBar = CreateBar()
你确定某些事情是错误的。试试吧; CreateBar
返回任何类型的柱线的实例,而不是SteelBar
。
正如 pycruft 所提到的,您不能将基类型的对象分配给子类型变量。我不明白你为什么要添加一个SteelBar
,因为你也有Material
属性。这对我来说似乎是多余的。
为了实现您要做的事情,您必须创建一个从头开始构建SteelBar
的新工厂方法。无论如何,它可能会将其作为Bar
返回。这将是工厂模式的实现。
但是,有关您要实现的目标的更多信息可能会有所帮助。
它一直告诉我不能隐式地从 下级
我为此使用的最好的例子是 Fruit
和 apple
.继承是一种"是"关系。 apple
是Fruit
但Fruit
不是apple
,因为它可以是orange
,banana
...
回到您的示例,SteelBar
是一个Bar
但Bar
不是SteelBar
因为它可以是 WoodenBar
这就解释了为什么你不能将超类转换为子类
你不能这样做:
SteelBar = B;
您已经创建了一个 Bar 类型的新对象,并尝试将其分配给 SteelBar 类型的引用。
使用诸如接口之类的抽象会更容易实现...例如,不可获取的和IPhysical的,而不是基类...
我将仅在 GUI 表示中使用 BaseClass 以便于显示它们,并且我会强制基类实现所需的接口。
您也可以选择使用密封的显示对象,并采用IMeasureable或IPhysical...
确定你的问题是你试图向上投射:
Bar B = CreateBar();
SteelBar = B;
这是不对的,因为即使 SteelBar 必须是 Bar
型(因为它继承自),也不能向后完成相同的操作。
反之则合法:
SteelBar B = CreateBar();
Bar = (Bar)B;
很简单,您正在尝试在Bar
中存储SteelBar
的引用,而它可能是另一种柱线类型,例如WoodenBar
。
考虑这个例子:
public class Super {
}
public class Sub : Super {
}
如果创建对象 Super,则无法将其指定为 Sub,因为它不是"Sub"。OO编程允许您根据派生较少的类"处理"对象,但这个简单的事实仍然存在:
您创建了一个超级而不是潜艇。
从超级创建 Sub 的唯一方法是创建一个新的 Sub 并复制属性值。像AutoMapper这样的工具可以很好地快速完成此操作,否则您最终会得到一堆平凡的脆弱代码。