【问题标题】:C# base inheritanceC# 基继承
【发布时间】:2012-06-16 16:56:21
【问题描述】:

这个问题一直困扰着我,我现在已经写了 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();,但我在这里做了很长的路。

【问题讨论】:

  • 我不清楚你为什么不使用构造函数。这将大大简化您的问题。
  • 你不会在CreateBar()中返回值
  • 在这种情况下 - 在我的系统中,我正在为其中包含 1 到 500 个项目的东西创建扩展。
  • SteelBar = new SteelBar();将是语法错误,您尝试在此处声明的变量的名称是什么
  • 钢筋就是钢筋,这就是您所知道的。你不知道钢筋就是钢筋。据你所知,酒吧可能是湿吧。同样,狗也是动物。但是动物可能是也可能不是狗。它可能是一只猫。您返回动物的方法可以返回任何东西,试图将其分配给狗是行不通的。尝试将钢筋分配给钢筋是同样的事情。关键是 steelbar 可以隐式转换为 bar,而不是相反。您基本上似乎对继承的功能有错误的认识。

标签: c# class inheritance


【解决方案1】:

考虑这个例子:

public class Super {
}

public class Sub : Super {
}

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

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

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

【讨论】:

    【解决方案2】:

    我很确定你的问题是你试图向上转型:

    Bar B = CreateBar();
    SteelBar = B;
    

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

    反之亦然:

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

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

    【讨论】:

      【解决方案3】:

      它一直在告诉我不能隐式地从一个 下层阶级

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

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

      【讨论】:

        【解决方案4】:

        当然,使用接口等抽象会更容易实现......例如IMeasureable 和 IPhysical 而不是基类...

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

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

        【讨论】:

          【解决方案5】:

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

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

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

          【讨论】:

            【解决方案6】:

            这是你的问题:

            Bar B = CreateBar();
            SteelB = B;
            

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

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

            因为SteelBar 是某种类型的条形,但反之则不正确..

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

            你确定某事是假的。试试吧; CreateBar 返回一个条形的实例任何类型,而不是SteelBar

            【讨论】:

              【解决方案7】:

              您将使用 构造函数,而不是使用方法 (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# 编程指南中的Constructors

              【讨论】:

              • 正如问题中所述,这实际上是实现预期结果的方式
              • @KyleTrauberman 这是不正确的 - 基类构造函数总是被隐式调用。如果要调用默认的无参数构造函数以外的构造函数,则只需要指定它。如果不调用基类构造函数之一,就无法构造子类。
              • 嗯,这是一个巨大的欢乐杀戮。所以你告诉我的是我不能创建一个基类,使用它,然后在需要时扩展它而不重新创建基类?我将停止以这种方式使用扩展,然后开始在类中添加引用。
              • @Charles 您不能将基类分配给子类 - 不。当然,反过来也可以。通常,您只需将其创建为最派生类并使用它 - 因为派生类始终可以用作基类...(请参阅:en.wikipedia.org/wiki/Liskov_substitution_principle
              • @Charles 是的——你不能“扩展”已经创建的类。在这种情况下,构图或装饰效果很好。请参阅en.wikipedia.org/wiki/Decorator_pattern 了解一个想法。
              【解决方案8】:

              你不能这样做:

              SteelBar = B;
              

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

              【讨论】:

                猜你喜欢
                • 2016-02-15
                • 1970-01-01
                • 2011-08-27
                • 2016-12-12
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-04-18
                • 2017-09-05
                相关资源
                最近更新 更多