2016-08-03 8 views
1

オブジェクトタイプ参照(別のインスタンスを保持する)を使用して関数を呼び出す:私は場合は、mainメソッドを持つ別のクラスのメインメソッドで今私は犬のクラスのように説明した

class Dog { 
//data members 
void bark() { 
    //Bark Algorithm 
    } 
} 

を次のようになります。

Object dog = new Dog(); 
dog.bark(); 

「犬」リファレンスが犬のインスタンスを保持しているため、動作しませんか?なぜこれは有効ではないのですか?

ここで使用される言語はJavaです。

ご協力ありがとうございます。

答えて

1

Javaは非常に厳密に型指定されています。 Javaコンパイラは実行時ではなく、コンパイル時にメソッドのチェックを行います。 dogObjectと宣言されているので、Objectクラスにbark()という名前のメソッドがあるかどうかコンパイラがチェックします。そうではないので、コンパイラエラーをスローします。これがJavaの設計方法です。

これは多型そのものの制限ではなく、Javaでの多型の実装の制限であることに注意してください。このまったく同じコードは、JVM上で動作するGroovyのようなより動的に型付けされた言語で完全にコンパイル(および動作)します。

+0

これは多形性への制限ですか? –

+0

Java **の多形性**の制限です。 'dog'は' Object'として宣言されているので、 'bark()'メソッドはありません。それはJavaの型設計の問題です。 – m0skit0

+0

ありがとうございました。私はこのコンセプトが今私にははっきりしていると思います。 Javaの**厳密に型付けされた**性質を正当化するには、この制限がその設計に含まれていなければなりません。 –

0

私はここで解決策を得たと思います。コンパイラは、参照型に基づいて呼び出す関数を決定し、参照が保持するインスタンス型には決定しません。

この場合のように、ちょうど犬のクラスのように、他の多くの動物も)インスタンス化され、オブジェクトの参照は、ヒープ上の自分のオブジェクトを参照するために使用することができ、すべてではないが(吠えことができますすることができますすることができます。したがって、コンパイラは、関数呼び出しをインスタンス型ではなく参照型に基づいて決定する必要があります。

+0

あなたの答えは完全に正確ではありません

。ただし、この回答を削除して元の質問の編集としてコメントを追加する必要があります。 – Kariem

-2

あなたがdogの種類について確認している場合は、常に型キャスト

Object dog = new Dog(); 
((Dog)dog).bark(); 

安全なバージョン行うことができます。

Object dog = new Dog(); 
if (dog instanceof Dog) 
    ((Dog)dog).bark(); 

がUPD

ポリモーフィズムの例:

interface Animal { 
} 


interface Barkable extends Animal { 
    void bark(); 
} 

class Dog implements Barkable { 
    @Override 
    public void bark() { 
     System.out.println("woof-woof"); 
    } 
} 

class Cat implements Barkable { 
    @Override 
    public void bark() { 
     System.out.println("meow"); 
    } 
} 

class SilentCreature implements Animal { 
} 

.... 


Animal animal = new Dog(); 
animal.bark(); 

animal = new Cat(); 
animal.bark(); 

animal = new SilentCreature(); 
// new SilentCreature() returns new animal, but not Barkable 
animal.bark(); // as Animal doesn't have method bark() this code won't compile 
0123を
+0

それは多態性の欠点ではないでしょうか? –

+0

複数の動物タイプに樹皮法を適用させたい場合は、樹皮法とのインタフェースを使用し、それに型変換する必要があります。 –

+0

@BobBrinksは、クラスと樹皮の動作との間にHAS-A関係があるべきであることを示唆していますか? –

1

Objectクラスには、barkというメソッドはありません。したがって、コードはコンパイルされません。

しかし、これはコンパイラが参照型に基づいてどのメソッドを純粋に呼び出すかを決定するわけではありません。参照タイプによって、CANコールが決定されますが、インスタンスタイプによってメソッドが決定されます。WILLが呼び出されます。これが多型の基本的なメカニズムです。例えば、

class Animal 
{ 
    void makeSound() 
    { 
     //Generic animal sound algorithm 
    } 
} 

class Dog extends Animal{ 
    void makeSound() 
    { 
     //Bark Algorithm 
    } 
} 

その後

Animal dog = new Dog(); 
Animal animal = new Animal(); 
dog.makeSound(); //calls bark 
animal.makeSound(); //generic animal sound 
+0

インターフェイスを使用する方が良い例になるかもしれません。 –

+0

さて、Animalは一般的なものですが、私はインターフェイスの知識を前提にしたくありませんでした。 – Kariem

+0

@ Kariemしたがって、スーパークラスで利用可能なメソッドだけが、そのクラスの参照を使用して呼び出すことができます。それは、インスタンスのタイプによってメソッドがどのように機能するかに依存しますが、 –

関連する問題