1

次のコード:

class Base{}

class Agg extends Base{

   public String getFields(){
    String name="Agg";
    return name;
   }
}

public class Avf{
   public static void main(String args[]){
   Base a=new Agg();
   //please take a look here
   System.out.println(((Agg)a).getFields());  // why a needs cast to Agg? 

  }
}

私の質問は:なぜ私たちはに置き換えることができない ((Agg)a).getFields()a.getFields()ですか?なぜキャストを型変換する必要があるのaですか?そして、それgetFields()はクラスで定義されていないBaseので、クラスAggはこのメソッドをその基本クラスから拡張しません。getFields()しかし、クラスでメソッドを定義した場合 、次Baseのようになります。

class Base{
    public String getFields(){
        String name="This is from base getFields()";
        return name;
    }
}

すべてが大丈夫だろう。その 場合、((Agg)a).getFields()はa.getFields()と同等です。

コード内

Base a=new Agg();    

この行aは、の参照がAgg()あり、クラスのメソッドを直接呼び出すことができることを意味しますかAgggetFields()しかし、クラスでメソッドを定義しないと、なぜ違いがあるのBaseでしょうか。誰かが私にこれを説明できますか?

4

5 に答える 5

11

System.out.println(((Agg)a).getFields()); // why a needs cast to Agg?

Baseと呼ばれるメソッドがないためgetFieldsです。

宣言

Base a;

...を使用するときに使用するインターフェイスをコンパイラに通知しますanew Agg();次にそれに割り当てることは重要ではありません、あなたがしなければならないインターフェースaまだBaseです。そして、BaseがないのでgetFields、使用しようとするgetFieldsとコンパイルエラーになります。

Base a=new Agg();

この行aは、の参照がAgg()あり、クラスのメソッドを直接呼び出すことができることを意味しますかAgg

これは、オブジェクトへの参照がa 含まれAggていることを意味しますが、そのオブジェクトへのインターフェイスは、ではBaseなくによって定義されているため、(キャストなしで、キャストは危険であり、可能な限り回避)。AggAggBase

コードがによって定義されたメソッドまたはフィールドにアクセスする必要がある場合Aggは、変数(または私の例では引数)を宣言する必要があります。宣言する必要がAgg aありBase aます。

これは、一般的なOOP、特にJavaでのOOP実装に関する基本的なことです。オブジェクトへのインターフェースと、オブジェクトの実装には大きな違いがあります。あなたの例では、あなたBase aは本当にであることを知っていますAggが、これを考慮してください:

void foo(Base a) {
    // Use `a` here...
}

// A long time later in a class far, far away...
xyz.foo(new Agg());

a明らかにここでは、コンパイラは、で定義されていないメソッドまたはフィールドの使用を許可するべきではありませんBase。これはコードでも同じ状況ですが、あまり明白ではありません。

于 2012-11-02T17:07:43.247 に答える
2

私の質問は、なぜ((Agg)a).getFields()をa.getFields()に置き換えることができないのですか?なぜキャストを型変換する必要があるのですか?

これを本当に理解しているように思えます-コンパイラは(である)getFieldsのコンパイル時タイプのメソッドを見つけられないため、コンパイル時エラーが発生します。aBase

これが質問の本当の根性であるように思われます:

 Base a=new Agg();

この行は、aがAgg()の参照を持ち、aがクラスAggのメソッドを直接呼び出すことができることを意味しますか?しかし、BaseクラスでgetFields()メソッドを定義しないと、なぜ違いがあるのでしょうか。誰かが私に説明できますか?

これは、コンパイラが利用可能であることがわかっBaseているのは、のメンバーにのみアクセスできることを意味します。同じ名前のメソッドが複数ある場合は、コンパイル時の型にも過負荷解決が適用されます。

ただし、実行時には、実際には型のオブジェクトのメソッドを呼び出しているAggため、で宣言されたメソッドをAgg オーバーライドBaseすると、の実装Aggが使用されます。

基本的に、式のコンパイル時タイプに基づいてコンパイル時に行われる決定と、オブジェクトの実行時タイプに基づいて実行時に(JVMによって)行われる決定を区別する必要があります。値はを参照します。

于 2012-11-02T17:12:25.460 に答える
1

この行Base a=new Agg();は、
1-ローカル変数aがタイプBase2に属していることを意味します-
タイプAgg3の新しいオブジェクトがあります
-変​​数aはそのオブジェクトを参照します
オブジェクトと変数は異なる(ただし互換性のある)タイプを持っています。変数aのタイプはBaseであるため、a.getFields()はありません。
ただし、変数はAggクラスのオブジェクトを参照するため、AggにキャストしてgetFieldsにアクセスできます
。変数は(おおよその種類の)ポインタです。オブジェクトではなく、オブジェクト。

于 2012-11-02T17:16:53.867 に答える
1

タイプAggはより具体的なタイプであるためBasea宣言のタイプはですBase。宣言の左側にあるものは、オブジェクトのタイプを表します。実際aにはメソッドgetFields()が含まれていますが、アップキャストされているため、メソッドはタイプに隠されていBaseます。HeadFirstJavaの本をお勧めします。これらの概念を明確にするのに役立ちます。

于 2012-11-02T17:17:20.207 に答える
1

クラスインスタンスは、そのメソッド(クラス定義で定義されている)とそのスーパークラスのメソッド(オブジェクトクラスなど)にアクセスできます。したがって、参照変数 "a"を持つクラスベースのインスタンスは、メソッドgetFields()にアクセスできません。クラス構造でもスーパークラスでも定義されていません。以下のように型キャストする場合:

((Agg)a)

基本的に、タイプを(Base)からタイプ(Agg)に変更します。BaseのサブクラスであるAggは、メソッドgetFields()を定義します。

于 2012-11-02T17:25:05.470 に答える