0

私は次のコードを持っています。なぜこれが機能するのですか?鋳造は必要ですか?

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!");
  }
4

5 に答える 5

4

いいえ、ダウンキャストは不要であり、事実上ノーオペレーションです。

  1. instanceofチェックにより、ダウンキャストが失敗しないことが保証されます。
  2. すべてのダウンキャスト参照は、ステートメントFoodによってすぐにアップキャストされます。return

関数は次のようにもっとコンパクトに書くことができます:

  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、多くの場合、設計が不適切であることを示しています。の新しいサブクラスを追加することを想像してみてくださいFoodinstanceofここで、この方法で使用するコード内のすべての場所を再検討し、適切に変更する必要があります。

より良い設計は、基本クラスで適切な仮想関数を定義し、それを派生クラスでオーバーライドすることです。

于 2012-05-18T14:44:11.460 に答える
3

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-18T14:45:03.427 に答える
1

したがって、これをまとめると、ミルク、パン、肉は食品のサブクラスである(食品を「拡張」する)ことを意味します。これが事実だと思います。もしそうなら、それがコンパイルされる理由です。

つまり、牛乳、パン、肉は食品として扱うことができますが、それらの奥深くは異なります(つまり、1つはパン、1つは牛乳、もう1つは肉であり、それぞれが食品のメンバー変数に加​​えて独自のメンバー変数を持っています。アイテム)

Javaでは、変数fはFoodおよびFoodのサブクラスを受け入れます。ただし、通過する食品(肉、牛乳、パンを含む)は、特定の種類の食品を無視して、食品オブジェクトとして扱われます。

それらがどのような種類のFoodサブクラスであるかを正確に知りたい場合は、instanceof演算子を使用して調べてから、アクションを実行できます。次に、それらを実際の特定のタイプにキャストして、それらのオブジェクトから特定のメソッドを呼び出します。

あなたのコード:あなたがしているのは実際の食料品を返すことだけなので、キャストは必要ありません。Javaは、デフォルトでミルク、パン、肉を食品として扱い、デフォルトで食品の代わりに返品できます。一方、Meat、Bread、またはMilkオブジェクトの特定のプロパティにアクセスする場合は、キャストが必要になります。これらのfは単なる食品ではなく、肉、パン、またはミルクであることをJavaに伝える必要があります。たとえば、MilkクラスにgetFatPercent()メソッドがある場合は、((Milk)f).getFatPercent()を実行する必要があります。

Foodのサブクラスがさらに存在する可能性があると仮定すると、コードは次のようになります。

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");
}
于 2012-05-18T14:59:40.813 に答える
0

鋳造は必要ありません。いいえ、elseの後にelseは必要ありません。実際、elseは常にオプションです

于 2012-05-18T14:44:50.807 に答える
-1

注意してください、elseステートメントは常にオプションではありません。たとえば、elseステートメントがないため、以下のコードはコンパイルされません。check()メソッドはaを返す必要があり、 andステートメントbooleanの両方が実行に失敗する場合があると考えているため、コンパイラは混乱します。したがって、check()は:を返しません。ifelse-ifboolean

static boolean check(int x) {
    if (x < 5) {
        return true;
    } else if (x >= 5) {
        return false;
    }
}

public static void main(String[] args) {
    check(5);
}
于 2019-03-29T07:53:46.093 に答える