기술나눔

[JAVA 입문] Day15 - 인터페이스

2024-07-12

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

[JAVA 입문] Day15 - 인터페이스



인터페이스는 왜 있는 걸까요?
우리 모두 알고 있듯이 상속은 하위 클래스의 공통 추상화를 상위 클래스로 추출하고전체 시스템의 공통성그러나 코드를 저장하려면 상황도 있습니다. 대부분의 하위 클래스에는 특정 공통성이 있지만 소수의 하위 클래스에만 이 기능이 없습니다. 그러면 이 공통성이 상위 클래스에 기록되면 상속됩니다. 이는 불합리합니다. 이 몇 가지 하위 카테고리입니다.
예를 들어, 고양이와 개는 수영할 수 있지만 토끼는 수영할 수 없습니다. 이때 부모 클래스에 "swimming" 메소드를 정의하면 토끼가 자신만의 수영 메소드를 상속받는 것은 무리입니다. 두 메서드의 작성 형식과 이름이 각각 일치하지 않을 수 있습니다. 따라서 우리는 이 두 하위 클래스에서 "swimming" 메서드의 작성 사양을 제한하는 새로운 개념을 정의해야 합니다.이 시점에서 우리는 "수영"을 정의할 수 있습니다.상호 작용, 인터페이스에서 추상 메서드 swim()을 정의한 다음 고양이와 개가 이 인터페이스에 연결되도록 하여코드 통일
요약하자면 인터페이스는 다음과 같습니다.규칙, 여러 클래스에 대한 규칙을 동시에 정의해야 하는 경우 다음을 사용해야 합니다.상호 작용

1. 인터페이스는 "행동"의 추상화입니다.

인터페이스는 사물의 유형을 나타내지 않습니다. 인터페이스는규칙, 인터페이스를 매개변수로 메소드에 전달할 수 있습니다.
"트럭이건, 삼륜차이건, 인력이건, 움직일 수만 있다면 유용할 것입니다."

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

2. 인터페이스의 정의 및 사용

  • 인터페이스는 키워드 인터페이스로 정의됩니다.
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

세 개의 하위 클래스가 서로 다른 것을 먹기 때문에 부모 클래스를 먼저 작성하세요. 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

개구리 클래스를 작성할 때 상위 클래스 상속과 상위 클래스의 추상 메소드 다시 작성에 주의하고 수영 인터페이스 구현에 주의하십시오.

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

개 클래스를 작성할 때 부모 클래스를 상속하고 수영 인터페이스를 구현하기 위해 부모 클래스의 추상 메서드를 재정의하는 데 주의하세요.

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

토끼 클래스를 작성할 때 부모 클래스를 상속하고 추상 메서드만 재정의하면 되며 수영 인터페이스를 구현할 필요는 없다는 점에 유의하세요(수영은 할 수 없습니다).

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 이전에는 추상 메소드만 가능했습니다.기본수정자는 공용 추상입니다. 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 인터페이스의 기본 메소드

메소드 본문이 있는 메소드는 주로 다음을 위해 인터페이스에 정의됩니다.인터페이스 업그레이드인터페이스가 불변일 수 없다는 점을 고려하면 업그레이드하려면 새로운 메소드를 추가해야 합니다. 이러한 메소드가 추상 메소드인 경우 이 메소드를 구현 클래스에서 동시에 구현해야 하는데 이는 매우 번거롭고 번거로운 작업입니다. 업그레이드가 메소드 본문이 있는 메소드를 사용하는 경우에는 구현 클래스를 추가로 수정할 필요가 없으며 수정이 필요한 경우 다시 작성하여 수정할 수도 있습니다.

  • 인터페이스에서 기본 메소드를 정의하려면 키워드를 사용해야 합니다. 기본 그루밍.
  • 형식: 공개 기본 반환 값 유형 메서드 이름(매개변수 목록) { }
  • 예: 공개 기본 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

두 개의 기본 메서드는 동일한 이름을 갖습니다. 구현 클래스가 이 두 인터페이스를 동시에 구현하는 경우 이 기본 메서드를 다시 작성해야 합니다.

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 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

하지만 사실 둘은 다른 방식이다.

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 정적 반환값 형식 메서드 이름(매개변수 목록) { }
  • 예시 2: 개인 정적 무효 메소드() { }
  • 사용법: 정적 메서드를 제공합니다.
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. 다른 클래스가 어댑터 클래스의 객체를 생성하는 것을 방지하기 위해 중간 어댑터 클래스를 추상화로 장식합니다.

상호 작용:

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