5

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

假设我正在使用 Rectangle 类来表示金属条。(这比动物效果更好)

所以说基类称为“Bar”。

private class Bar
{
   internal Rectangle Area;
}

所以。现在我们制作一个矩形,比如 300 x 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();,但我在这里做了很长的路。

4

8 回答 8

16

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# 编程指南中的构造函数。

于 2012-06-13T17:13:22.477 回答
3

这是你的问题:

Bar B = CreateBar();
SteelB = B;

B是任何一种酒吧。您正在尝试将其分配给SteelBar. 错了,它可能是任何类型的酒吧(铜、木头、Tiki,...)。你可以这样做:

SteelBar sb = new SteelBar();
Bar b = sb;

因为 aSteelBar是某种酒吧,但反过来不是真的..

另外,我确定我可以调用 SteelBar = CreateBar()

你确定某事是假的。尝试一下; 返回任何类型CreateBar的 bar 的实例,而不是.SteelBar

于 2012-06-13T17:15:34.177 回答
1

正如 pycruft 提到的,您不能将基本类型的对象分配给子类型变量。我不明白你为什么要添加一个SteelBar,因为你也有一个Material属性。这在我看来是多余的。

为了实现您想要做的事情,您必须创建一个SteelBar从一开始就构建 a 的新工厂方法。Bar无论如何,它可能会返回它。这将是工厂模式的实现。

但是,有关您要实现的目标的更多信息可能会有所帮助。

于 2012-06-13T17:16:23.880 回答
1

它一直在告诉我不能从下层阶级隐含地创建上层阶级

我为此使用的最佳示例是Fruitand apple。继承是一种“is-a”关系。一个appleis-aFruit但 aFruit 不是一个apple,因为它可以是一个orange, banana...

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

于 2012-06-13T17:17:20.723 回答
0

你不能这样做:

SteelBar = B;

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

于 2012-06-13T17:13:13.890 回答
0

我很确定您的问题是您正在尝试向上转换:

Bar B = CreateBar();
SteelBar = B;

这是不对的,因为即使 SteelBar 必须是类型Bar(因为它继承自),也不能向后执行相同的操作。

相反是合法的:

SteelBar B = CreateBar();
Bar = (Bar)B;

很简单,您正试图存储SteelBarin的引用Bar,而它可能是另一种条形类型,例如WoodenBar.

于 2012-06-13T17:14:45.237 回答
0

当然,这会更容易通过诸如接口之类的抽象来实现……例如 IMeasureable 和 IPhysical 而不是基类……

我将仅在 GUI 表示中使用 BaseClass 以便于显示它们,并且我将强制基类实现所需的接口。

您还可以选择使用密封的 DisplayObject 并采用 IMeasurable 或 IPhysical ...

于 2012-06-13T17:16:42.787 回答
0

考虑这个例子:

public class Super {
}

public class Sub : Super {
}

如果您创建对象 Super,则不能将其分配为 Sub,因为它不是“Sub”。OO 编程允许您根据较少派生的类来“处理”对象,但这个简单的事实仍然存在:

您创建了一个 Super 而不是 Sub。

从 Super 创建 Sub 的唯一方法是创建一个新的 Sub 并复制属性值。像 AutoMapper 这样的工具可以很好地快速完成这项工作,否则你最终会得到一堆平凡而脆弱的代码。

于 2012-06-13T17:20:59.120 回答