私はこのインターフェースを持っています:
public interface Animal {
public void Eat(String name);
}
そして、このコードはインターフェースを実装しています:
public class Dog implements Animal {
public void Eat(String food_name) {
System.out.printf(food_name);
}
public static void main(String args[]) {
Animal baby2 = new Dog(); //HERE!!!!!!!!!!!!!!!!!!!!!!
baby2.Eat("Meat");
}
}
私の質問は、なぜコードが機能するのですか?インターフェイスをインスタンス化できません。ただし、この場合、インターフェイスはインスタンス化されています(「HERE !!!!!!!!!!!!!」というコメントが付いています)。
ここで何が起きてるの?
いいえ、そうではありません-Dog
をインスタンス化していますが、Dog
はAnimal
であるため、変数をAnimal
として宣言できます。インターフェイスAnimal
をインスタンス化しようとすると、次のようになります。
Animal baby2 = new Animal();
それを試して、コンパイラが恐怖で悲鳴を上げるのを見てください:)
Dog
はインターフェイスではありません:Dog
はクラス that 実装Animal
インターフェイスです。
ここで不愉快なことは何もありません。
以下のように、インターフェースの匿名実装をインスタンス化できることに注意してください。
Animal animal = new Animal() {
public void Eat(String food_name) {
System.out.printf("Someone ate " + food_name);
}
};
以下のコードを考えてみましょう:
interface Cookable {
public void cook();
}
class Food {
Cookable c = new Cookable() {
public void cook() {
System.out.println("anonymous cookable implementer");
}
};
}
上記のコードはanonymous inner classのインスタンスを作成しますが、ここでは、新しいジャストインタイムクラスはCookable インターフェース。そして、これが構文を見る唯一の時間であることに注意してください:
new Cookable()
cookableは、非抽象クラス型ではなくインターフェイスです。考えてみてください:インターフェイスをインスタンス化することはできません、それでもコードはそのように見えます。しかし、もちろん、Cookable object
をインスタンス化するのではなく、新しいanonymous implementer of Cookable
のインスタンスを作成します。
次の行を読むことができます:
Cookable c = new Cookable(){}
「(明らかに、Cookableインターフェースを実装するクラスのオブジェクトを参照する、Cookable型の参照変数を宣言します。しかし、はい、まだありません。 Cookableを実装するクラスなので、今ここで1つ作成します。クラスの名前は必要ありませんが、それはCookableを実装し、この波括弧は新しい実装クラスの定義を開始します。」
匿名インターフェースの実装者にとって重要なことは覚えておく必要があります-実装できるインターフェースは1つだけです。匿名の内部クラスが複数のインターフェイスを実装するということを言うメカニズムはありません。実際、匿名の内部クラスは、クラスを拡張することも、インターフェースを同時に実装することもできません。 innveクラスは、名前付きクラスのサブクラスで、インターフェースを直接実装しないか、単一のインターフェースを実装するかのいずれかを選択する必要があります。
したがって、匿名の内部クラスの場合を除き、インターフェイスをインスタンス化する試みにだまされないでください。 以下は無効です:
Runnable r = new Runnable(); // can't instantiate interface
一方、以下は、Runnableインターフェース(匿名実装クラス)の実装者をインスタンス化するため、正当です:
Runnable r = new Runnable() {
public void run(){ }
};
あなたは私の記事を読むことができます こちら 。
ここで観察しているのは、 [〜#〜] solid [〜#〜] の Dependency inversion アスペクトです。
コードは、具体的な実装をインスタンス化することにより、Animal
コントラクトの抽象化に依存しています。 「someオブジェクトをインスタンス化していますが、実際にそのオブジェクトが何であるかis、それはAnimal
インターフェイスのコントラクトにバインドされます。」
たとえば、次のような宣言を考えてみましょう。
List<String> wordList = new LinkedList<>();
Map<Integer, String> mapping = new HashMap<>();
どちらの場合も、リストとマップの主な側面は、List
とMap
の一般的な契約に従うことです。
Animal baby2 = new Dog(); //HERE!!!!!!!!!!!!!!!!!!!!!!
確かに、あなたは動物をインスタンス化していない。 Dogインスタンスを参照するだけです。 Javaでは、スーパークラス参照を取得できます。
あなたが言う時:
Animal baby2 = new Dog();
参照タイプは、具象実装(Dog)を指すAnimal(インターフェース)です。オブジェクトタイプDogは具象であり、インスタンス化できます。この場合、犬が動物を指す限り、犬を指します。インターフェイス内のすべてのメソッドの具体的な実装では、参照タイプを作成できます
あなたが何かをしたなら、
Animal baby2 = new Animal(); // here you are actually instantiating
これは抽象的な実装から具象オブジェクトを作成しようとしているため無効です。
全体像を把握するには:
Animal [] Zoo = new Animal[10] ; // is also correct
しかし、なぜ ?
全体の考えは、上の表に異なる種類の動物を10匹入れることができるということです。このための唯一の条件は、動物園に入るすべての動物がインターフェイスAnimalを実装する必要があることです。
public interface Animal {
void Eat();
}
class Wolf implements Animal { void Eat (){
System.out.println("Wolf eats meat ") ;}}
Class Zebra implements Animal{ void Eat (){
System.out.println("Zebra eats the grass ") ;}}
class test {
public static void main (String args []) {
Animal [] Zoo = new Animal[2] ;
Zoo[0] = new Wolf() ;
Zoo[1] = new Zebra() ;
//so you can feed your animals in Zoo like this
for (int i=0 ; i<Zoo.lenght;i++) {Zoo[i].Eat();}
}
}
これはポリモーフィズムの場合です。「動物」オブジェクトを作成しているようですが、そうではありません。実行時に計算される「犬」オブジェクトを作成しています。「動物」は契約として機能します。インターフェースを直接インスタンス化することはできませんが、サブクラスをアップキャストすることでタイプとして使用できます。匿名クラスを使用して、オブジェクトを「動物」タイプとしてインスタンス化することもできます。
Animal baby2 = new Dog(); //upcasting polymorphically
Animal baby3=new Animal(){
public void Eat(String food){System.out.println("fdkfdfk"); }
}
//You can instantiate directly as anonymous class by implementing all the method of interface
Interface Animalは、Dogクラスのデータ型として機能します。実際には、インターフェイスまたはデータ型ではなく、Dogクラスをインスタンス化しています。
インターフェイスAnimal
はインスタンス化されませんが、Dog
によって実装されます。そして、Dog
がインスタンス化されます
実際に、インターフェイスをインスタンス化できます。ここにあなたが試すことができるコードがあります
public static void main(String args[]) {
System.out.println(new Animal() {
public String toString() {
return "test";
}
});
}
このプログラムは正常に実行され、test
と表示されます。
ここではインターフェイスを参照しているだけですが、インスタンス化はクラスによってのみ行われます。例えば
Animanl a = new Dog Animal a-変数はnew Dogを参照-現在メモリが割り当てられている