2013-02-13 58 views
2

假设您有一个名为Food的类,并且您有派生类Banana,Apple和Orange。你有一个FoodProcessor方法,大多数情况下,它可以处理任何类型的食物,但偶尔需要知道它正在处理什么类型的食物,以便做特定类型的事情,比如剥离香蕉,核心苹果,或挤橙。C#标记派生类实例的最好方法

所以你的FoodProcessor需要Food参数。 FoodProcessor检测Food实例的特定派生类型的最佳方法是什么?

回答

1

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

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

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

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

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

如果你寻找特定的类型,你现在需要知道每种可能的类型,并且在将来,这是不可扩展的。

这当然假定你不想使用直多态,就像其他答案所描述的一样。

0
void FoodProcessor(Food food) 
{ 
    if(food is Banana) 
     ... 
    else if(food is Apple) 
     ... 

    ... 
    etc 
} 

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

1

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

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及其子类之间的继承关系。

0

我想使它成为抽象的,在每种食品实现它:

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(); 
    } 
} 
+0

我不喜欢多态性答案,因为你基本上是在告诉食物去处理它自己。 (在某些情况下,这会很好,但不是我在这个问题中寻找的东西。)它看起来像“is”关键字是我正在寻找的答案。谢谢大家。 – 2013-02-13 22:09:06

+0

@EdwardNedHarvey这只是一个例子。在我上面的例子中,您可以简单地调用“准备”,然后继续处理食物处理器的“过程”方法中的食物。 – 2013-02-13 22:57:11

+0

@EdwardNedHarvey更重要的是,我觉得这样的设计在SRP的方向发展,其中食品并不比一个数据结构更与OP将增加一类为每个责任,如准备,处理,后处理等。这相当于丢弃封装,这比SRP规则更重要。更不用说使用'is'运算符进行特定类型处理的紧密耦合性和缺乏可伸缩性,这些运算符可以干净地封装在派生类型中。 FWIW – 2013-02-13 23:15:31