我有以下代码。为什么这是可行的?有必要进行选型吗?
static public Food createMeal(Food f)
throws Exception
{
if (f instanceof Bread)
{
return (Bread) f;
}
else if (f instanceof Meat)
{
return (Meat) f;
}
else if (f instanceof Milk)
{
return (Milk) f;
}
throw new Exception("NotAFood!");
}发布于 2012-05-18 22:45:03
这里不需要else,因为如果满足前面的条件,那么return将简单地转义整个方法:
if (f instanceof Bread)
{
return (Bread) f;
}
if (f instanceof Meat)
{
return (Meat) f;
}
if (f instanceof Milk)
{
return (Milk) f;
}
throw new Exception("NotAFood!");不,这里没有必要向下转换。实际上,你可以像这样编写等价的函数:
static public Food createMeal(Food f) throws Exception {
if(f instanceof Bread || f instanceof Meat || f instanceof Milk) {
return f;
}
throw new Exception("NotAFood!");
}发布于 2012-05-18 22:44:11
不,向下转换是不必要的,并且实际上是无操作的:
instanceof检查确保向下转换不会失败;return语句向上转换回Food。函数可以编写得更简洁,如下所示:
static public Food createMeal(Food f) throws Exception {
if ((f instanceof Bread) || (f instanceof Meat) || (f instanceof Milk)) {
return f;
} else {
throw new Exception("NotAFood!");
}
}话虽如此,在条件语句中使用instanceof通常是一个糟糕设计的标志。想象一下添加一个新的Food子类。现在,您必须重新查看以这种方式使用instanceof的代码中的每一个位置,并对其进行适当的修改。
更好的设计是在基类中定义一个合适的虚函数,然后在派生类中覆盖它。
发布于 2012-05-18 22:59:41
因此,如果编译完成,就意味着牛奶、面包和肉类是食物的子类(它们“扩展”了食物)。我假设情况就是这样。如果是这样,那么这就是编译的原因。
现在,这意味着牛奶、面包和肉类可以被视为食物,但在本质上它们是不同的(例如,一个是面包,一个是牛奶,一个是肉类,每个都在食品项的成员变量之上有自己的特殊成员变量)
在Java中,变量f接受任何食物和食物的任何子类。但是,您传递的任何食物(包括肉类、牛奶和面包)都将被视为食物对象,而忽略它们是哪种食物。
如果你想找出它们到底是哪种食品子类,你可以使用instanceof操作符来找出,然后采取行动。然后将它们强制转换为实际的特定类型,以调用这些对象中的特定方法。
你的代码:你所做的只是返回一个实际的食物项目,所以转换是不必要的。默认情况下,Java将牛奶、面包和肉类视为食品,并且默认情况下可以在食品项的位置返回它们。另一方面,如果您想访问一个Meat、Bread或Milk对象的特定属性,那么您将需要强制转换。您需要告诉java,这些f不仅仅是一种食物,而是一种肉、面包或牛奶。例如,如果您的Milk类有一个getFatPercent()方法,那么您需要执行((Milk)f).getFatPercent()
假设可以有更多的食品子类,您的代码等同于:
static public Food createMeal(Food f) throws Exception {
if(f instanceof Milk || f instanceof Meat || f instanceof Bread)
return f;
else
throw new Exception("Not a valid Food");
}https://stackoverflow.com/questions/10654734
复制相似问题