【问题标题】:OOP C# Question: Making a Fruit a PearOOP C# 问题:将水果变成梨
【发布时间】:2011-03-01 22:37:39
【问题描述】:

鉴于我有一个设置了一些属性的 Fruit 实例,并且我想将这些属性放入一个新的 Pear 实例中(因为这个特殊的 Fruit 恰好具有梨的品质),实现这一目标的最佳方法是什么效果?

例如,我们不能简单地将水果转换为梨,因为并非所有水果都是梨:

public static class PearGenerator {
    public static Pear CreatePear () {

        // Make a new generic fruit.
        Fruit genericFruit = new Fruit();

        // Upcast it to a pear. (Throws exception: Can't cast a Fruit to a Pear.)
        Pear pear = (Pear)genericFruit;

        // Return freshly grown pear.
        return ( pear );
    }
}

public class Fruit {
    // some code
}

public class Pear : Fruit {

    public void PutInPie () {
        // some code
    }

}

谢谢!

更新:

我不控制“new Fruit()”代码。我的出发点是我有一个可以使用的水果。我需要以某种方式把那个水果变成一个新的梨。是否可以一一复制所有属性?

【问题讨论】:

  • 这不是向上转换,您正在尝试将超类型“向下转换”为派生类型,这是不合法的
  • 你想让你的未知水果做什么梨的事情?你怎么能保证 Fruit 能够做这些 Pear 的事情呢?
  • 你真的不希望你的代码变成梨形,是吗? {G}

标签: c# .net oop


【解决方案1】:

因为你创造的水果不是梨!


编辑:如果您已经有一个Fruit 并且需要从中创建一个Pear,那么是的,您别无选择,只能将所有属性复制到一个新的 Pear 对象。理想情况下,这应该在您专门为此目的创建的 Pear 构造函数中完成。

【讨论】:

  • 是的,把它想象成“所有的梨都是水果(这就是为什么你可以从梨到水果)但不是所有的水果都是梨(所以你不能强迫它成为梨)”跨度>
【解决方案2】:

梨是一种水果。

水果不一定是梨。

【讨论】:

    【解决方案3】:

    这不是梨。换行试试

    Fruit genericFruit = new Fruit();
    

    与:

    Fruit genericFruit = new Pear();
    

    【讨论】:

    • 这是关键。了解这一点以及何时使用它,您就掌握了一个重要的 OO 概念。
    【解决方案4】:

    downcast 失败,因为创建的实例是Fruit,要使其成为Pear,请将代码更改为

        // Make a Pear - it looks like a fruit, tastes like a fruit,
        // and quacks like a fruit. It must be a fruit.
        Fruit genericFruit = new Pear();
    
        // Downcast it to a pear. 
        Pear pear = (Pear)genericFruit;
    

    向下转换查看实际类型,而不是声明的类型 - 但您不知道实际类型是什么(除非您使用 is/as 进行测试)。这就是为什么它有点危险,大多数人都尽量避免向下转换。

    编辑:要将水果变成梨,您可以自己创建一个新梨并尽可能地对其进行初始化。从水果到梨,所有水果共有的一些特性可能被复制。但这也可能就像试图将一个方形钉子放入一个圆孔中,混合你的隐喻并最终得到水果泥。

    【讨论】:

      【解决方案5】:

      如果 Pear 定义了一堆新东西......而你创建了 Fruit。

      如果您将 Fruit 向上转换为 Pear,应该将 Pear 中的所有额外内容设置为什么?

      这都是未定义的东西。因此为什么它不允许!

      【讨论】:

        【解决方案6】:

        当你进行投射时,你实际上并没有改变任何数据,如果你愿意的话,只是改变了“标签”。如果你有一个梨被施放为水果,那么它可以被施放回梨,但如果它一开始就不是梨,施放不会把它变成梨。

        【讨论】:

          【解决方案7】:

          就像 Evgeny 所说的那样,所做的事情是不合法的,因为它不是类型安全的。如果不允许,将超类型向下转换为派生类型。

          有多种方法可以解决您的问题,具体取决于您的情况

          泛型、动态(仅限 C# 4.0)、抽象类、接口。

          【讨论】:

            【解决方案8】:

            如果您不是 Fruit 的作者,而是 Pear 的作者,那么不同的设计可能会有所帮助:

            Pear 类更改为更多FruitWrapper 类可能会更好。此类将持有对Fruit 的引用,而不是更具体的Fruit。它可以有自己的功能(首先你不想使用Fruit 的原因),并将水果类型的功能传递给它里面的Fruit。如果它需要使用需要 Fruit 的库代码,只需将它持有的那个传递给...

            【讨论】:

              【解决方案9】:

              一定要继承吗?

              ...我认为梨 -> 水果的例子让这变得很难......这是一个例子,对吗?

              创建你的 Pear 类怎么样:

              public class Pear { 
              
                  public Fruit {get; set;}
              
                  public void Pear(add pear properties, Fruit fruit)
                  {
                       // assign pear properties
                       Fruit = fruit;
                  }
              
                  public void PutInPie () { 
                      // some code 
                  } 
              
              }
              

              这可能并不理想,但它是一个想法。

              祝你好运,

              帕特里克

              【讨论】:

                【解决方案10】:

                您可以为 Pear 创建一个接受 Fruit 实例的新构造函数。

                【讨论】:

                  【解决方案11】:

                  这个例子让我想起了this article 中的那个。看看那里关于继承与组合的有趣讨论。想想fragile base class 问题。要从一个对象映射到另一个对象,您可以使用AutoMapper

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-05-07
                    • 1970-01-01
                    相关资源
                    最近更新 更多