【问题标题】:C# best way to mark derivative class instancesC# 标记派生类实例的最佳方法
【发布时间】:2014-04-05 00:28:52
【问题描述】:

假设您有一个名为 Food 的类,并且您有一个名为 Banana、Apple 和 Orange 的派生类。您在某处有一个 FoodProcessor 方法,在大多数情况下,它可以处理任何类型的食物,但有时需要知道它正在处理什么类型的食物,以便执行特定类型的操作,例如剥香蕉皮、去核苹果,或者挤橙子。

所以你的 FoodProcessor 接受 Food 参数。您的 FoodProcessor 检测 Food 实例的特定衍生类型的最佳方法是什么?

【问题讨论】:

    标签: c# inheritance


    【解决方案1】:

    您应该使用多态性,每个Food 子类将定义一个方法process(),而FoodProcessor 类将简单地调用该方法。

    食物处理器

    public void process(Food f) {
        f.process(); 
    }
    

    苹果

    public void process() {
        Console.WriteLine("Core the apple.");
    }
    

    香蕉

    public void process() {
        Console.WriteLine("Peel the banana.");
    }
    

    橙色

    public void process() {
        Console.WriteLine("Squeeze the orange.");
    }
    

    通过这种方式,您可以利用 Food 与其子类之间的继承关系。

    【讨论】:

      【解决方案2】:

      在测试对象的类型时,我喜欢使用is关键字,像这样:

      if(myFood is Bannana)
        Peel((Bannana)myFood);
      

      我更喜欢is,因为它还会检查对象是否实现了接口。

      说到接口,如果您有某些类型可以执行特定操作,您可能需要考虑使用接口。检查特定类型需要了解可能使用的不同类型,但是,如果检查接口,则可能会出现实现此接口的新类型,而无需更改代码来处理它们:

      if(myFood is IPeelable)
        Peel((IPeelable)myFood)
      else if(myFood is ICoreable)
        Core((ICoreable)myFood)
      

      如果您寻找特定的类型,您现在和将来都需要了解所有可能的类型,这不是非常可扩展的。

      这当然假设您不想使用直接多态性,正如其他答案之一所述。

      【讨论】:

        【解决方案3】:

        我会将其抽象化并在每种食物中实现:

        abstract class Food {
            public abstract void Prepare();
        }
        
        class Banana : Food {
            public override void Prepare() {
                Peel();
            }
        }
        
        class Apple : Food {
            public override void Prepare() {
                Core();
            }
        }
        

        那么你会有:

        class FoodProcessor {
            public void Process(Food food) {
                food.Prepare(); // preparation of the food
                food.Process();
            }
        }
        

        【讨论】:

        • 我不喜欢多态性的答案,因为你基本上是在告诉 Food 自己去处理。 (在某些情况下,这很好,但不是我在这个问题中寻找的。)看起来“is”关键字是我正在寻找的答案。谢谢大家。
        • @EdwardNedHarvey 这只是一个例子。在我上面的示例中,您可以简单地调用Prepare,然后继续在食品加工机的Process 方法中处理食品。
        • @EdwardNedHarvey 更重要的是,我觉得这种设计正朝着 SRP 的方向发展,其中 Food 只不过是一种数据结构,OP 将为每个职责添加一个类,例如准备,处理、后处理等...相当于丢弃封装,比SRP规则更基础。更不用说使用is 运算符进行特定类型的处理时的紧密耦合和缺乏可伸缩性,它们可以干净地封装在派生类型本身中。 FWIW
        • @SimonWhitehead 添加一个编辑建议一个接口,你会得到我的支持 =P 他没有给出任何理由建议我们真的需要一个基础抽象类,它有可能将我们锁定在一个特定的抽象(以后可能真的很糟糕)。
        • 抱歉——我并不是说多态性的答案在任何方面都是错误的或不好的——这确实是一个非常好的答案。我只是说我不希望我现在要解决的问题中存在多态性,因为 FoodProcessor 实际上知道很多 Food 不知道的上下文。食物不需要知道齿轮和电力和其他食物,它们实际上是现实生活问题的一部分,但在这个论坛问题中没有提到。我接受了“是”的答案,因为它是对所提问题的直接回答,而不是暗示需要更改问题。
        【解决方案4】:
        void FoodProcessor(Food food)
        {
            if(food is Banana)
                ...
            else if(food is Apple)
                ...
        
            ...
            etc
        }
        

        编辑:如果您可以使用其他答案中提到的多态性,则忽略此

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-07-06
          • 2018-11-03
          • 1970-01-01
          • 1970-01-01
          • 2012-06-13
          • 1970-01-01
          • 1970-01-01
          • 2013-11-16
          相关资源
          最近更新 更多