1

キャスト/アップキャストの問題を解決するための実行可能な戦略はありますか? アップキャストとダウンキャストが許可されている場合は理解していますが、質問に複数のオブジェクトが含まれる傾向がある場合、すぐに混乱する傾向があります。たとえば、次のような質問に対する答えを見つけるための最善のアプローチは何ですか。

質問: 次のプログラムをコンパイルした結果はどうなりますか?

interface Inter{}
class Base implements Inter{}
class Derived extends Base{}

class ZiggyTest2{

    public static void main(String[] args){

        Base b = new Base();
        Derived d = new Derived();
        Inter i = (Base)b;
        i = (Base)d;
        Derived bd = (Derived)b;
        b = (Base)i;        
    }   
}

私は答えにはあまり興味がありませんが、質問を解決するためのアプローチにもっと興味があります。上記のようなアップキャスト/ダウンキャストの質問を解決するために使用できるアプローチ/戦略はありますか? たとえば、参照/オブジェクトを紙に描いて、視覚的な表現を得ることができますか?

ありがとう

4

4 に答える 4

3

アップキャストとダウンキャストに関する素晴らしい記事を次に示します。

記事より引用 --

まず、キャストによってオブジェクト自体が実際に変更されるのではなく、異なるラベルを付けているだけであることを理解しなければなりません。

「オブジェクトの型は何ですか?」と自問してみてください。そして、それをクラス階層 (インターフェースを含む) 内の任意の先行クラスにキャストすることが合法であることを思い出してください。

あなたの場合、 と の 2 つのオブジェクトを作成していBaseますDerived。にはまたは のラベルを付けることができ、 には 、 または のラベルBaseを付けることができます。したがって、コードは問題なくコンパイルされます。ただし、実行時に にキャストしようとすると、ClassCastException が発生します。InterBaseDerivedInterBaseDerivedBase bDerived bd

于 2011-12-27T15:23:39.433 に答える
3

いくつかの簡単なルールがあります

  • クラスの先行者にキャストできます(オブジェクトまで)(失敗することはありません)
  • サブクラスにキャストできます-これは実行時に失敗する可能性があります
  • それを実装するクラスからインターフェイスにキャストできます(失敗することはありません)
  • インターフェイスからiplemnetingクラスにキャストできます-これは実行時に失敗する可能性があります

最初の 2 つのルールは、ti インターフェイスにも適用されます。

UML クラス図を描い て視覚化することができます (実装 = 実現、拡張現実のみを使用)。グラフをナビゲートすると、矢印の方向に安全に移動できます。他の方法でナビゲートすると、実行時に安全ではなくなります。そして、extend/implements 関係なしでナビゲートすることは不可能です。

于 2011-12-27T15:23:06.027 に答える
1

私にとっては、最初にこれらのタイプの階層を描きたいと思います。あなたの質問のために、タイプの「レベル」は次のとおりです。


Inter(より高い)

Base(より高い)

Derived


オブジェクトの「レベル」はその作成時に決定され、オブジェクトはその作成レベルに応じて「上がる」ことしかできず、下がることはできません。たとえば、Objectbはオブジェクトとして作成されるBaseため、レベルはBase。です。bを説明するためにどのタイプが使用されていても、b缶をアップキャストすることはできますInterが、ダウンキャストすることはできません。を使用してbを記述するDerived場合、その作成レベルはであるため、にダウンキャストできます。InterBaseBase

于 2011-12-27T15:29:45.793 に答える
1

操作対象のオブジェクトが同じ階層にある場合、キャストは確実にコンパイルされますが、実行時に失敗する可能性があります。

例えば:

class Animal { }
class Dog extends Animal { }
class Bulldog extends Dog { }

あなたが書く場合:

Animal animal = new Animal();
Dog d = (Dog) animal;

上記のコードはコンパイルされますが、実行時に失敗します。コンパイラができることは、2 つの型が同じ継承ツリーにあるかどうかを確認することだけだからです。コンパイラは、実行時に機能する可能性のあるものを許可します。しかし、何かが決して機能しないことをコンパイラーが確実に認識している場合、コンパイラーは実行時にエラーをスローします。例えば

Animal animal = new Animal();
Dog d = (Dog) animal;
String s = (String) animal;

コンパイラは String と Dog が同じ階層にないことを認識しているため、これは確実に失敗します。

インターフェイスにも同じ規則が適用されます。

それが役に立てば幸い。

于 2011-12-27T15:24:19.400 に答える