C#基继承

C#基继承,c#,class,inheritance,C#,Class,Inheritance,这个问题一直困扰着我,我现在已经写了4个包装。我肯定我做错了,我需要弄清楚我的理解在哪里分支 假设我使用矩形类来表示金属条。(这比动物更有效) 因此,基类被称为“Bar” 所以。现在我们做一个矩形,比如说300个单位乘以10个单位 private Bar CreateBar() { Bar1 = new Bar1(); Bar1.Area = new Rectangle(new Point(0,0), new Size(300,10)); return Bar1; }

这个问题一直困扰着我,我现在已经写了4个包装。我肯定我做错了,我需要弄清楚我的理解在哪里分支

假设我使用矩形类来表示金属条。(这比动物更有效)

因此,基类被称为“Bar”

所以。现在我们做一个矩形,比如说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的steelbar。因此,我最终得到了一个300×10矩形的钢筋,以及一个空的或空的材料字符串。然后我将材料设置为钢

当我在我的程序中尝试类似的东西时,它总是告诉我不能从一个较低的类隐式地创建一个较高的类。考虑到我看到的所有动物遗传的例子,我想这就是为什么遗传存在的原因,但我希望有人能澄清我的观点

另外,我确信我可以调用
SteelBar=CreateBar()但我在这里做了很长一段路。

你不能这样做:

SteelBar = B;

您已经创建了一个Bar类型的新对象,并试图将其分配给SteelBar类型的引用。

您应该使用构造函数,而不是方法(
CreateBar
):

public SteelBar()
{
    this.Material = "Steel";
}
然后,在SteelBar中,您可以调用基类构造函数:

public SteelBar()
{
    this.Material = "Steel";
}
基类构造函数将首先出现,因此您的区域将已经设置好。但是,您可以明确说明这一点,并在代码中显示:

public SteelBar()
    : base()
{
    this.Material = "Steel";
}
但是,这通常仅在您希望有一个接受参数的特定构造函数时使用


有关详细信息,请参阅《C#编程指南》。

我很确定您的问题在于您试图向上投射:

Bar B = CreateBar();
SteelBar = B;
这是不对的,因为即使钢条必须是
Bar
(因为它继承自)类型,也不能向后执行

反之则是合法的:

SteelBar B = CreateBar();
Bar = (Bar)B;
很简单,您试图在
Bar
中存储
SteelBar
的引用,而它可能是另一种条形类型,例如
WoodenBar

,这是您的问题:

Bar B = CreateBar();
SteelB = B;
B
是任何类型的条。您正试图将其分配给
钢条
。这是错误的,它可以是任何种类的酒吧(铜,木材,提基,…)。您可以这样做:

SteelBar sb = new SteelBar();
Bar b = sb;
因为钢棒是某种类型的钢棒,但事实并非如此

另外,我确信我可以调用SteelBar=CreateBar()
你肯定有些东西是假的。试试看
CreateBar
返回任何类型的条形图的实例,而不是pycruft提到的
SteelBar

,您不能将basetype对象指定给子类型变量。我不明白你为什么要添加一个
钢条
,因为你也有
材质
属性。我觉得这是多余的

为了实现您想要做的事情,您必须创建一个新的工厂方法,从一开始就构建一个
钢条。它可能会以
条的形式返回它。这将是该计划的实施


不过,关于您试图实现的目标的更多信息可能会有所帮助。

当然,使用接口之类的抽象会更容易实现。。。e、 g.IMeasureable和IPhysical而非基类

为了便于显示,我将仅在GUI表示中使用基类,并且我将强制基类实现所需的接口

您还可以选择使用一个密封的DisplayObject,它采用IMeasurable或IPhysical

它一直在告诉我不能从 下层阶级

我用的最好的例子是
水果
苹果
。继承是一种“是一种”关系。苹果是一种水果,但水果不是苹果,因为它可以是橘子,香蕉

回到您的示例中,
SteelBar
Bar
,但
Bar
不是
SteelBar
,因为它可以是
WoodenBar
这就解释了为什么不能将超类强制转换为子类

考虑以下示例:

public class Super {
}

public class Sub : Super {
}
如果创建超级对象,则无法将其指定为子对象,因为它不是“子对象”。OO编程允许您根据派生较少的类“处理”对象,但这个简单的事实仍然存在:

您已经创建了一个Super而不是Sub


从Super创建Sub的唯一方法是创建新Sub并复制特性值。像AutoMapper这样的工具可以很快地完成这项工作,否则您将得到一大堆平凡而脆弱的代码。

我不清楚您为什么不使用构造函数。这将大大简化您的问题。您不会在
CreateBar()
中返回值。在本例中,它会返回值-在我的系统中,我正在为包含1到500项的内容创建扩展。SteelBar=new SteelBar();这将是一个语法错误,您试图在此处声明的变量的名称是什么?steelbar是bar,这就是您所知道的全部。你不知道一根钢条就是一根钢条。酒吧可以是酒吧,你知道的。同样,狗也是一种动物。但是动物可能是也可能不是狗。它可能是一只猫。你返回动物的方法可以返回任何东西,试图将其分配给狗是行不通的。尝试将钢筋指定给钢筋也是一回事。关键是,steelbar可以隐式转换为bar,而不是相反。本质上,您似乎对继承的功能有错误的认识。事实上,这就是您将如何实现所需的结果,如中所述question@KyleTrauberman这是不真实的-基类构造函数总是隐式调用的。您只需要在以下情况下指定它
public class Super {
}

public class Sub : Super {
}