技術共有

[JAVA入門] Day15 - インターフェース

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

[JAVA入門] Day15 - インターフェース



なぜインターフェースがあるのでしょうか?
ご存知のとおり、継承とは、サブクラス内の共通の抽象化を親クラスに抽出し、システム全体の共通性ただし、コードを節約するには、状況も発生します。ほとんどのサブクラスには特定の共通性がありますが、この機能を持たないサブクラスはほんのわずかです。その場合、この共通性が親クラスに書き込まれると、それが継承され、これは非合理的です。これらのいくつかのサブカテゴリです。
たとえば、猫と犬は泳ぐことができますが、ウサギは泳げません。このとき、親クラスに「水泳」メソッドが定義されている場合、ウサギが独自の水泳メソッドを記述するのは不合理です。それぞれ、2 つのメソッドの記述形式と名前が一致しない可能性があります。したがって、これら 2 つのサブクラスの「スイミング」メソッドの記述仕様を制約する新しい概念を定義する必要があります。この時点で、「水泳」を定義できます。インターフェース、インターフェイスで抽象メソッド swim() を定義し、猫と犬がこのインターフェイスに接続できるようにします。コードの統一
要約すると、インターフェイスはルール、複数のクラスのルールを同時に定義する必要がある場合は、次を使用する必要があります。インターフェース

1. インターフェースは「動作」を抽象化したもの

インターフェイスはもののタイプを表すのではなく、インターフェイスが表すのはルール, そのため、インターフェイスをパラメータとしてメソッドに渡すことができます。
「トラックでも、三輪車でも、人力でも、動かせるものなら役に立ちますよ」。

搬家(车的对象);
  • 1
搬家(搬家公司);
  • 1
public interface 运输 {
	...
}
  • 1
  • 2
  • 3
public void 搬家(运输的接口 c) {
	...
}
  • 1
  • 2
  • 3

2. インターフェースの定義と使用

  • インターフェースは、キーワード「interface」で定義されます。
public interface 接口名 {}
  • 1
  • インターフェイスはインスタンス化できません。つまり、インターフェイスを使用してオブジェクトを作成することはできません。
  • インターフェイスとクラスの違いは次のとおりです。成し遂げる関係は、implements キーワードによって表されます。
public class 类名 implements 接口名 {}
  • 1
  • インターフェイスのサブクラス (実装クラス) は、インターフェイス内のすべての抽象メソッドをオーバーライドするか、それ自体が抽象クラスです。
  • インターフェイスとクラス間の実装関係は次のようになります。単一の実装、 こともできます複数の実装
public class 类名 implements 接口名1 , 接口名2 {}
  • 1
  • 実装クラスはクラスを継承しながら複数のインターフェイスを実装できます。
public class 类名 extends 父类 implements 接口名1 , 接口名2 {}
  • 1

練習する: インターフェイスと抽象クラスを備えた標準 Javabean クラスを作成します。

 青蛙		属性:名字,年龄		行为:吃虫子,蛙泳
 狗			属性:名字,年龄		行为:吃骨头,狗刨
 兔子		属性:名字,年龄		行为:吃胡萝卜
  • 1
  • 2
  • 3

最初に親クラスを作成します。3 つのサブクラスは異なるものを使用するため、eat() を抽象メソッドとして定義できます。

package oopInterface;

public abstract class Animal {
    private String name;
    private int age;

    public Animal() {
    }

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public abstract void eat();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

インターフェイスのスイムの書き込み:

package oopInterface;

public interface Swim {
    public abstract void swim();
}
  • 1
  • 2
  • 3
  • 4
  • 5

frog クラスを作成するときは、親クラスの継承と親クラスの抽象メソッドの書き換え、およびスイミング インターフェイスの実装に注意してください。

package oopInterface;

public class Frog extends Animal implements Swim {
    public Frog() {
        super();
    }

    public Frog(String name, int age) {
        super(name, age);
    }

    @Override
    public void swim() {
        System.out.println("青蛙在蛙泳。");
    }

    @Override
    public void eat() {
        System.out.println("青蛙在吃虫子。");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

Dog クラスを作成するときは、親クラスを継承し、親クラスの抽象メソッドをオーバーライドしてスイミング インターフェイスを実装することに注意してください。

package oopInterface;

public class Dog extends Animal implements Swim {

    public Dog(){
        super();
    }

    public Dog(String name, int age) {
        super(name,age);
    }
    @Override
    public void swim() {
        System.out.println("狗在狗刨。");
    }

    @Override
    public void eat() {
        System.out.println("狗在吃骨头。");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

Rabbit クラスを作成するときは、親クラスを継承して抽象メソッドをオーバーライドするだけでよく、スイミング インターフェイスを実装する必要はないことに注意してください (スイミングはできません)。

package oopInterface;

public class Rabbit extends Animal {

    public Rabbit() {
    }

    public Rabbit(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println("兔子在吃胡萝卜。");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

テストクラスを作成します。

package oopInterface;

public class Test {
    public static void main(String[] args) {
        Frog f = new Frog("小绿",23);
        f.eat();
        f.swim();
        System.out.println(f.getName() + ", " + f.getAge());
        Dog d = new Dog("大D", 24);
        d.eat();
        d.swim();
        System.out.println(d.getName() + ", " + d.getAge());
        Rabbit r = new Rabbit("兔子", 30);
        r.eat();
        System.out.println(r.getName() + ", " + r.getAge());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3. インターフェース内のメンバーの特徴

  • メンバー変数: インターフェイス内のメンバー変数は次のとおりです。絶え間ない, デフォルトでは public static Final が使用されます(書かなくても自動的にこのようにみなされます)。
  • コンストラクター: インターフェースいいえ施工方法。
  • メンバー メソッド: JDK7 より前では、メンバー メソッドは抽象メソッドのみでした。デフォルト修飾子は public abstract です。JDK8 以降では、メソッド本体を持つメソッドをインターフェイスで定義できます。JDK9 以降では、プライベート メソッドをインターフェイスで定義できます。

4. インターフェースとクラスの関係

  • クラス間の関係: 継承関係 - 単一継承のみで、多重継承はできませんが、多段階継承は可能です。
  • クラスとインターフェイスの関係: 実装関係 - 単独で実装することも、複数の実装で実装することもでき、クラスを継承しながら複数のインターフェイスを実装することもできます。
  • インターフェイス間の関係: 継承関係 - 単一継承または複数継承の場合があります。

知らせ:
1. クラスがインターフェイスを実装する場合、インターフェイス内のすべての抽象メソッドを実装するか、クラス自体も抽象クラスである必要があります。
2. クラスは複数のインターフェイスを実装できます。複数のインターフェイスを実装する場合は、次のようにする必要があります。全てインターフェースに実装されるすべての抽象メソッドが実装されます。
3. インターフェイスは複数のインターフェイスから継承できます。サブインターフェイスが複数のインターフェイスを継承し、実装クラスによって実装される場合、実装クラスはサブインターフェイスとそのすべての親インターフェイスを結合する必要があります。全てすべての抽象メソッドが実装されています。

練習する: インターフェイスと抽象クラスを備えた標準 Javabean クラスを作成します。

乒乓球运动员:姓名,年龄,学打乒乓球,说英语
篮球运动员:姓名,年龄,学打篮球
乒乓球教练:姓名,年龄,教打乒乓球,说英语
篮球教练:姓名,年龄,教打篮球
  • 1
  • 2
  • 3
  • 4
//Person类
package oopInterExp;

//因为直接创建顶层父类人的对象是没有意义的
//所以将其写为抽象类
public abstract class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
//Sporter类继承Person
package oopInterExp;

public abstract class Sporter extends Person {

    public Sporter(String name, int age) {
        super(name, age);
    }

    public Sporter() {
    }

    public abstract void learn();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
//Coach类继承Person
package oopInterExp;

public abstract class Coach extends Person {

    public Coach() {
    }

    public Coach(String name, int age) {
        super(name, age);
    }

    public abstract void teach();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
//SpeakEnglish接口
package oopInterExp;

public interface SpeakEnglishInter {
    public abstract void speakEnglish();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
//PingPongSporter继承Sporter,实现SpeakEnglish
package oopInterExp;

public class PingPongSporter extends Sporter implements SpeakEnglishInter {

    public PingPongSporter(String name, int age) {
        super(name, age);
    }

    public PingPongSporter() {
    }

    @Override
    public void learn() {
        System.out.println("学习乒乓球。");
    }

    @Override
    public void speakEnglish() {
        System.out.println("乒乓球运动员在说英语。");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
//PingPongCoach继承Coach,实现SpeakEnglish
package oopInterExp;

public class PingPongCoach extends Coach implements SpeakEnglishInter {
    public PingPongCoach() {
    }

    public PingPongCoach(String name, int age) {
        super(name, age);
    }

    @Override
    public void teach() {
        System.out.println("教乒乓球。");
    }

    @Override
    public void speakEnglish() {
        System.out.println("乒乓球教练在说英语。");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
//BasketballSporter继承Sporter
package oopInterExp;

public class BasketballSporter extends Sporter {

    public BasketballSporter(String name, int age) {
        super(name, age);
    }

    public BasketballSporter() {
    }

    public void learn() {
        System.out.println("学篮球。");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
//BasketballCoach继承Coach
package oopInterExp;

public class BasketballCoach extends Coach {

    public BasketballCoach() {
    }

    public BasketballCoach(String name, int age) {
        super(name, age);
    }

    public void teach() {
        System.out.println("教篮球。");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

5. インターフェースの新しいメソッド

5.1 JDK8 開始インターフェースの新しいメソッド

JDK7 より前は、インターフェイスでは抽象メソッドのみを定義できました。
JDK8 の新機能は次のとおりです。メソッド本体を持つメソッドをインターフェイスで定義できます (デフォルト方法または静的方法)。
JDK9 の新機能は、インターフェイスで定義できることです。プライベート方法。

5.1.1 インターフェースのデフォルトメソッド

メソッド本体を持つメソッドは、主にインターフェイスで定義されます。インターフェースのアップグレードインターフェースを不変にできないことを考慮すると、新しいメソッドを追加してアップグレードする必要があり、これらのメソッドが抽象メソッドの場合、このとき同時に実装クラスに実装する必要があり、非常に面倒です。同期は容易ではありません。アップグレードではメソッド本体を使用するため、実装クラスを追加で変更する必要はありません。変更が必要な場合は書き換えることもできます。

  • インターフェイスでデフォルトのメソッドを定義するには、キーワードを使用する必要があります デフォルト グルーミング。
  • 形式: public デフォルト戻り値型メソッド名(パラメータリスト) { }
  • 例: public デフォルト void show() { }
  • デフォルトのメソッドは抽象メソッドではないため、オーバーライドする必要はありません。ただし、書き換える場合は、書き換え時にデフォルトのキーワードを削除する必要があります。
  • publicは省略可能ですが、defaultは省略できません。
  • 複数のインターフェイスが実装されており、複数のインターフェイスに同じ名前のデフォルト メソッドが存在する場合、サブクラスはメソッドをオーバーライドする必要があります (オーバーライドしないと競合が発生します)。

インターフェイスInter1:

package oopInterface5;

public interface Inter1 {
    public abstract void method();
    public default void default_method() {
        System.out.println("Inter1接口中的默认方法");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

インターフェイスInter2:

package oopInterface5;

public interface Inter2 {
    public default void default_method() {
        System.out.println("Inter2接口中的默认方法");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2 つのデフォルト メソッドが同じ名前を持つ場合、実装クラスがこれら 2 つのインターフェイスを同時に実装する場合、このデフォルト メソッドを書き直す必要があります。

package oopInterface5;

public class InterImpl implements Inter1, Inter2 {

    @Override
    public void method() {
        System.out.println("抽象方法的实现");
    }

    @Override
    public void default_method() {
        System.out.println("重写接口中的默认方法");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

テストクラス:

package oopInterface5;

public class Test {
    public static void main(String[] args) {
            InterImpl ii = new InterImpl();
            ii.method();				//抽象方法的实现
            ii.default_method();		//重写接口中的默认方法
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
5.1.2 インターフェースの静的メソッド

JDK8 以降では、インターフェイスで静的メソッドを定義できるようになり、静的メソッドを変更する必要があります。
インターフェース内静的メソッド定義形式は次のとおりです。

  • public static 戻り値型メソッド名(パラメータリスト) { }
  • 例: public static void show() { }

インターフェイスの静的メソッドに関する注意事項:

  • 静的メソッドは渡すことしかできませんインターフェース名呼び出されますが、実装クラス名またはオブジェクト名を介して呼び出すことはできません。
  • public は省略できますが、static は省略できません。

インターフェースを書きます。

package oopInterface6;

public interface Inter {
    public abstract void method();

    public static void static_method() {
        System.out.println("接口中的静态方法");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

実装クラスを作成します。クラス内にはインターフェイス内のメソッドと同じ名前の静的メソッドもありますが、静的メソッドはオーバーライドできないため、これはオーバーライドされません。

package oopInterface6;

public class InteImpl implements Inter {
    @Override
    public void method() {
        System.out.println("重写接口中的抽象方法");
    }

    //这不叫重写
    public static void static_method() {
        System.out.println("我不是重写的Inter接口中的静态方法");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

しかし実際には、この 2 つは異なる方法です。

package oopInterface6;

public class Test {
    public static void main(String[] args) {
        InteImpl ii = new InteImpl();
        ii.method();						  //重写接口中的抽象方法
        Inter.static_method();               //调用接口中的静态方法
        InteImpl.static_method();           //调用实现类中的一个同名的静态方法
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

5.2 JDK9 開始インターフェースの新しいメソッド

5.2.1 インターフェースでプライベートメソッドを定義する
  • 形式1:プライベート戻り値型メソッド名(パラメータリスト) { }
  • 例 1: private void show() { }
  • 使用法: デフォルトのメソッドを提供します。
package oopInterface7;

public interface InterA {
    public default void show1() {
        System.out.println("show1开始执行");
        show3();
    }

    public default void show2() {
        System.out.println("show2开始执行");
        show3();
    }

    //普通的私有方法,给默认方法服务的
    private void show3() {
        System.out.println("记录程序在运行过程中的各种细节,这里有100行代码。");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 形式2:private static戻り値型メソッド名(パラメータリスト) { }
  • 例 2: private static void メソッド() { }
  • 使用法: 静的メソッドを提供します。
package oopInterface7;

public interface InterB {
    public static void show1() {
        System.out.println("show1开始执行");
        show3();
    }

    public static void show2() {
        System.out.println("show2开始执行");
        show3();
    }

    //普通的私有方法,给静态方法服务的
    private static void show3() {
        System.out.println("记录程序在运行过程中的各种细节,这里有100行代码。");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

6. インターフェースの適用

1. インターフェイスはルールを表し、動作を抽象化したものです。クラスに動作を持たせたい場合は、クラスに対応するインターフェイスを実装させるだけです。
2. メソッドのパラメータがインターフェースの場合、そのインターフェースを渡すことができます実装クラスのすべてのオブジェクト、このアプローチはインターフェイス多態性と呼ばれます。

7. アダプターの設計パターン

  • デザイン パターンは、分類されカタログ化された一連のコード設計エクスペリエンスであり、繰り返し使用され、ほとんどの人に知られています。デザイン パターンを使用する目的は、コードを再利用し、コードを他の人が理解しやすくし、コードの信頼性とプログラムの再利用性を確保することです。

アダプターを使用すると、コードを簡素化し、インターフェイスに抽象メソッドが多すぎてその一部のみを使用する必要がある場合に生じる不便を回避できます。
書き込み手順は一般的に次のとおりです。
1. 中間クラス XXXAdapter を作成して、対応するインターフェイスを実装します。
2. インターフェースに抽象メソッドの空の実装を実装します。
3. 実際の実装クラスに中間クラスを継承させ、必要なメソッドを書き換えます。
4. 他のクラスがアダプタクラスのオブジェクトを作成しないようにするために、中間アダプタクラスをabstractで修飾します。

インターフェース:

package AdapterDesignPattern;

public interface Inter {
    public abstract void method1();
    public abstract void method2();
    public abstract void method3();
    public abstract void method4();
    public abstract void method5();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

アダプタークラス:

package AdapterDesignPattern;

public abstract class InterAdapter implements Inter {
    @Override
    public void method1() {

    }

    @Override
    public void method2() {

    }

    @Override
    public void method3() {

    }

    @Override
    public void method4() {

    }

    @Override
    public void method5() {

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

実装クラス:

package AdapterDesignPattern;

public class InterImpl extends InterAdapter {
    //我需要用到哪个方法,就重写哪个方法就可以了
    @Override
    public void method5() {
        System.out.println("只要用第五个方法");
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10