1. インターフェースの紹介

今日は知識を学ぶ日です。もう 1 つの新しくて興味深いトピックはインターフェイスです。

インターフェイスの概念は、抽象化とポリモーフィズムの原理の子です。インターフェイスは、すべてのメソッドが抽象クラスである抽象クラスに非常に似ています。宣言方法はクラスと同じですが、interfaceキーワードを使用します。

interface Feline
{
   void purr();
   void meow();
   void growl();
}

インターフェイスに関する有益な事実をいくつか紹介します。

1. インターフェースの宣言

interface Drawable
{
   void draw();
}

interface HasValue
{
   int getValue();
}
  1. キーワードの代わりにclass、 と書きますinterface
  2. 抽象メソッドのみが含まれています(キーワードは記述しないでくださいabstract
  3. 実際、インターフェイスにはすべてのpublicメソッドが含まれています
2. インターフェースの継承

インターフェイスはインターフェイスのみを継承できます。ただし、インターフェイスには多くの親を持つことができます。これを別の言い方で言えば、Java にはインターフェースの多重継承があると言えます。例:

interface Piece extends Drawable, HasValue
{
   int getX();
   int getY();
}

3. インターフェースからのクラスの継承

クラスは複数のインターフェイスを継承できます (1 つのクラスからのみ)。これはimplementsキーワードを使用して行われます。例:

abstract class ChessItem implements Drawable, HasValue
{
   private int x, y, value;
   public int getValue()
   {
      return value;
   }

   public int getX()
   {
      return x;
   }

   public  int getY()
   {
      return y;
   }
}

ChessItem クラスは抽象として宣言されており、 を除くすべての継承されたメソッドを実装しますdrawつまり、ChessItemクラスには 1 つの抽象メソッド — が含まれていますdraw()

extendsとキーワードの技術的な意味はimplements同じで、どちらも継承です。この区別は、コードの可読性を向上させるために行われました。クラスは ( を介してextends) 継承され、インターフェイスは ( を介してimplements)実装されるとも言います。

4. 変数

ここが最も重要なことです。通常の変数はインターフェイス内で宣言できません(静的な変数は宣言できますが)。

しかし、なぜインターフェースが必要なのでしょうか? いつ使用されますか? インターフェイスには、クラスに比べて次の 2 つの強力な利点があります。



2. 「メソッドの説明」をその実装から分離する。

前に、クラスのメソッドを他のクラスから呼び出せるようにしたい場合は、メソッドにキーワードを付ける必要があるとpublic述べましたこれらのメソッドの一部をクラス内からのみ呼び出すようにするには、それらのメソッドをキーワードでマークする必要がありますprivate。つまり、授業のメソッドを「みんなが使うもの」と「自分だけが使うもの」の2つに分けています。

インターフェースは、この部門をさらに強化するのに役立ちます。最初のクラスを継承する「全員が使用する」特別なクラスと、「自分だけが使用する」2 番目のクラスを作成します。おおよそ次のようになります。

class Student
{
   private String name;
   public Student(String name)
   {
      this.name = name;
   }

   public String getName()
   {
      return this.name;
   }

   private void setName(String name)
   {
      this.name = name;
   }
interface Student
{
   public String getName();
}

class StudentImpl implements Student
{
   private String name;
   public StudentImpl(String name)
   {
      this.name = name;
   }

   public String getName()
   {
      return this.name;
   }

   private void setName(String name)
   {
      this.name = name;
   }
}
public static void main(String[] args)
{
   Student student = new Student("Alibaba");
   System.out.println(student.getName());
}
public static void main(String[] args)
{
   Student student = new StudentImpl("Ali")
   System.out.println(student.getName());
}

クラスを 2 つに分割します。インターフェイスと、インターフェイス継承するクラスです。そして、ここでの利点は何ですか?

多くの異なるクラスが同じインターフェイスを実装 (継承) できます。そして、それぞれが独自の動作を持つことができます。たとえば、インターフェイスArrayList LinkedListの 2 つの異なる実装がありますList

したがって、さまざまな実装だけでなく、実装クラス自体も非表示にします (コード内のインターフェイスのみが必要なため)。これにより、非常に柔軟な対応が可能になります。プログラムの実行中に、あるオブジェクトを別のオブジェクトに置き換えることができ、オブジェクトを使用するすべてのクラスに影響を与えることなく、オブジェクトの動作を変更できます。

これは、ポリモーフィズムと組み合わせると非常に強力な手法になります。今のところ、なぜこれを行う必要があるのか​​は明らかではありません。インターフェイスがあると、インターフェイスがない場合よりも作業がはるかに簡単になることを理解するには、まず、数十または数百のクラスを持つプログラムに遭遇する必要があります。


3. 多重継承

Java では、すべてのクラスは親クラスを 1 つだけ持つことができます。他のプログラミング言語では、多くの場合、クラスは複数の親クラスを持つことができます。これは非常に便利ですが、多くの問題も伴います。

Java の作成者は妥協点に達しました。クラスの多重継承は禁止しますが、インターフェースの多重継承は許可します。インターフェイスには複数の親インターフェイスを持つことができます。 クラスには複数の親インターフェイスを持つことができますが、親クラスは 1 つだけです。

なぜクラスの多重継承は禁止しているのに、インターフェイスの多重継承は許可しているのでしょうか? いわゆるダイヤモンド継承問題のため:

多重継承

B クラスが A クラスを継承する場合、B クラスは C クラスと D クラスについては何も知りません。したがって、適切と思われる A クラスの変数を使用します。C クラスも同じことを行います。A クラスの変数を使用しますが、方法が異なります。そして、これらすべてがDクラス内での紛争を引き起こします。

次の簡単な例を見てみましょう。3 つのクラスがあるとします。

class Data
{
   protected int value;
}
class XCoordinate extends Data
{
   public void setX (int x) { value = x;}
   public int getX () { return value;}
}
class YCoordinate extends Data
{
   public void setY (int y) { value = y;}
   public int getY () { return value; }
}

Data クラスにはvalue変数が格納されます。その XCoowned 子孫クラスはその変数を使用して値を格納しxYCoordinate子孫クラスはそれを使用して値を格納しますy

そしてそれはうまくいきます。別々に。しかし、XYCoowned クラスにXCoordinateと の両方のYCoordinateクラスを継承させたい場合は、壊れたコードが得られます。このクラスにはその祖先クラスのメソッドがありますが、それらは同じ . を持つため、正しく動作しませんvalue variable

ただし、インターフェイスは変数を持つことができないため、この種の競合は発生しません。したがって、インターフェースの多重継承が許可されます。