18

Animal は Dog のスーパークラスで、Dog には bark というメソッドがあります

public void bark()
{
    System.out.println("woof");
}

次の点を考慮してください。

Animal a = new Dog();
if (a instanceof Dog){
    a.bark();
}

何が起こるか?

  1. 割り当ては許可されていません
  2. bark の呼び出しが許可され、実行時に "woof" が出力されます
  3. bark の呼び出しは許可されていますが、何も出力されません
  4. bark を呼び出すと、コンパイル時エラーが発生します
  5. bark を呼び出すと実行時エラーが発生する

オブジェクトが犬かどうかを確認しているので、2 と言いました。dog は bark メソッドを含むクラスであるため、そうである場合はそれを呼び出して :s を出力します

ここで私の理解は正しいですか?

4

9 に答える 9

33

Animal には bark というメソッドがないため、これはコンパイルされません。すべての犬は動物ですが、すべての動物が犬であるとは限りません。すべての犬は吠えますが、すべての動物が吠えるわけではありません。

于 2009-05-22T17:08:45.327 に答える
27

いいえ - 答えは;

4) bark の呼び出しによりコンパイル時エラーが発生する

bark メソッドは、割り当てられた型 Animal のメソッドとして定義されていないため、コンパイル時間の問題が発生します。これはキャストによって解決できます。

((Dog)a).bark();
于 2009-05-22T17:10:13.907 に答える
12

キーは次の行にあります。

Animal a = new Dog();

の新しいインスタンスDogが作成されましたが、その参照は によってa型であると宣言されていますAnimal。したがって、 を参照するaと、 はnew Dogとして処理されますAnimal

したがって、メソッドをAnimal持っていない限りbark、次の行でコンパイラ エラーが発生します。

a.bark();

aが のインスタンスであるかどうかがテストされ、実際Doga instanceof Dogが返されますがtrue、変数aは依然として 型であるため、ステートメントAnimal内のブロックは.ifaAnimal

これは、事前に変数に型が割り当てられ、コンパイル時にチェックされて型が一致することを確認する、静的型付け言語の機能です。このコードが実行時に型がチェックされる動的型付け言語で実行された場合、次のようなことが許可される可能性があります。

var a = new Dog();
if (a instanceof Dog)
    a.bark();

a.bark()はインスタンスが の場合にのみ実行されることが保証されているDogため、 への呼び出しbarkは常に機能します。ただし、Java は静的に型付けされた言語であるため、このタイプのコードは許可されていません。

于 2009-05-22T17:11:20.130 に答える
6

Head First Java では、テレビのリモコンをリファレンスとして使用し、TV をリファレンスが指すオブジェクトとして非常によく例えます。リモコンにオン、オフ、チャンネルのアップとダウン、音量のアップとダウンのボタン (方法) しかない場合は、テレビにどんな優れた機能があるかは関係ありません。リモコンからできるのは、これらのいくつかの基本的なことだけです。たとえば、リモコンにミュート ボタンがない場合、テレビをミュートすることはできません。

Animal リファレンスは、Animal メソッドについてのみ知っています。基礎となるオブジェクトが他のメソッドを持っているかどうかは関係ありません。アニマル参照からそれらにアクセスすることはできません。

于 2009-05-22T17:19:36.860 に答える
4

それは 4 です。一般的な動物 (コードで言うところの a です) に吠えるように頼むことはできません。あなたは簡単に言うことができたので

Animal a = new Cat();

樹皮線には、あなたがそうしなかったことを知る方法がありません。

于 2009-05-22T17:10:14.967 に答える
4

スーパークラス オブジェクトからサブクラス メソッドを出力することが目的の場合は、次のように動作します。

Animal a = new Dog(); if (a instanceof Dog){ a.bark(); } に変更する代わりに

Animal a = new Dog();

if (a instanceof Dog){ 
    Dog d = (Dog) a; 
    d.bark();
}  

これにより、スーパークラスがサブクラスにキャストされ、出力されます。設計は悪いですが、どの子クラス オブジェクトが動的に指されているかを知る 1 つの方法です。

于 2011-05-12T21:06:12.673 に答える
3

Java(私が知っている言語のみ)では、空のメソッドを作成してスーパークラスで呼び出すことができます。次に、サブクラスでそれをオーバーライドして、必要なことを行うことができます。このようにして、スーパー クラスはそのサブクラスのメソッドを呼び出します。

public class Test {
    public static void main(String[] args){
        Snake S = new Snake();
        Dog d = new Dog();
    }
}


class Animal{ //Super Class
    public Animal(){
        bark(); //calls bark when a new animal is created
    }
    public void bark(){
        System.out.println("this animal can't bark");
    }
}



class Dog extends Animal{ //Subclass 1
    @Override
    public void bark(){
        System.out.println("Woof");
    }
}



class Snake extends Animal{//Subclass 2
    public void tss(){
    }
}

このコードは、Snake のオブジェクトを呼び出してから、Dog のオブジェクトを呼び出します。これをコンソールに書き込みます:

this animal can't bark
Woof

Snake には bark メソッドがないため、スーパー クラスのメソッドが呼び出されます。最初の行をコンソールに書き込みます。Dog には bark メソッドがあるため、代わりにスーパー クラスが呼び出します。2 行目をコンソールに書き込みます。

于 2014-05-04T14:52:40.200 に答える
2

参考までに、これは良いデザインではありません。

この形式のコードがあるときはいつでも:

if (x instanceof SomeClass)
{
   x.SomeMethod();
}

型システムを悪用しています。これはクラスを使用する方法ではなく、保守可能なオブジェクト指向コードを記述する方法でもありません。もろいです。複雑です。これは悪いです。

基本クラスでテンプレート メソッドを作成できますが、基本クラスに存在し、サブクラスでオーバーライドされるメソッドを呼び出す必要があります。

于 2009-05-22T17:41:56.970 に答える
1

「オブジェクトが犬であるかどうかを確認しているので、2 と言いました。犬は樹皮メソッドを含むクラスであるため、そうであれば、それを呼び出して :s を出力します」

あなたの論理的根拠は正しいですが、それはそれが機能する方法ではありません。

Java は静的型付き言語です。つまり、オブジェクトが応答する可能性のあるメソッドの有効性は、コンパイル時に検証されます。

あなたは小切手を考えるかもしれません:

if( a instanceof Dog ) 

しますが、実際にはそうではありません。コンパイラが行うことは、宣言された型 (この場合は Animal ) の「インターフェイス」に対してチェックすることです。「インターフェース」は、Animal クラスで宣言されたメソッドで構成されます。

スーパークラスAnimalでbark()メソッドが定義されていない場合、コンパイラは次のように言います。

コーディング中に「時々」タイプミスをするため、これは役に立ちます (たとえば、代わりに barck() と入力します)。

コンパイラがこれについて警告しない場合は、「実行時」にそれを見つける必要があり、常に明確なメッセージがあるとは限りません (たとえば、IE の javascript は「予期しないオブジェクト」のようなことを言います)。

それでも、Java のような静的型付け言語を使用すると、呼び出しを強制できます。この場合、「キャスト」演算子 () を使用しています。

このような

1. Animal a = new Dog();
2.  if (a instanceof Dog){
3.     Dog imADog = ( Dog ) a;
4.     imADog.bark();
5. }

3 行目では、Dog 型に「キャスト」しているため、コンパイラは bark が有効なメッセージかどうかを確認できます。

これは、「私はここのプログラマーです。私が何をしているのか知っています」というコンパイラーへの指示です。そして、コンパイラ、チェック、Ok、dog、メッセージ bark() を受け取ることができます。続行します。ただし、実行時に動物が犬でない場合は、実行時例外が発生します。

キャストは、次のように短縮することもできます。

if( a instanceof Dog ) {
   ((Dog)a).bark();  
}

それは実行されます。

したがって、正解は4 です。bark の呼び出しにより、コンパイル時エラーが発生します

これが役立つことを願っています。

于 2009-05-22T17:38:39.423 に答える