[프로그래머스 자바 입문] 인터페이스(Interface)

4 분 소요

인터페이스(interface)

  • 서로 관계가 없는 물체들이 상호작용하기 위해 사용하는 장치나 시스템
  • 인터페이스는 다른 클래스를 작성할 때 기본이 되는 틀을 제공하면서, 다른 클래스 사이의 중간 매개 역할까지 담당하는 일종의 추상 클래스이다.
  • 생성자, 필드, 일반 메소드도 포함할 수 있는 추상 클래스와 다르게 인터페이스는 추상메소드와 상수만을 포함할 수 있다.

인터페이스의 정의

  • 추상 메소드상수를 정의할 수 있다.

     public interface TV {
       public int MAX_VOLUME = 100;
       public int MIN_VOLUME = 0;
         
       public void turnOn();
       public void turnOff();
       public void changeVolume(int volume);
       public void changeChannel(int channel);
     }
    
  • 인터페이스에서 변수를 선언하면 컴파일 시 자동으로 아래와 같이 변경된다.

    public static final int MAX_VOLUME = 100;
    public static final int MIN_VOLUME = 0;
    
  • 인터페이스에서 정의된 메소드는 모두 추상 메소드이다. 선언된 메소드는 컴파일 시 자동으로 다음과 같이 변경된다.

     public abstract void turnOn();
     public abstract void turnOff();
     public abstract void changeVolume(int volume);
     public abstract void changeChannel(int channel);
    
  • 인터페이스의 모든 필드는 public static final이어야 하며, 모든 메소드는 public abstract이어야 한다.

    • 이 제어자는 모든 인터페이스 공통으로 적용되는 부분이므로 생략 가능.
    • 이렇게 생략된 제어자는 컴파일 시 자바 컴파일러가 자동으로 추가.

인터페이스의 구현

  • 인터페이스를 추상 클래스와 마찬가지로 직접 인스턴스를 생성할 수는 없다.
  • 따라서, 인터페이스의 추상 메소드를 구현할 클래스를 작성해야 한다.
  • implements 키워드를 이용하여 구현한다.

    public class LedTV implements TV {
      
      // 인터페이스의 메소드 오버라이딩
      public void turnOn() {
        System.out.println("켜다");
      }
      public void turnOff() {
        System.out.println("끄다");
      }
      public void changeVolume(int volume) {
        System.out.println(volume + "(으)로 볼륨조정하다.");
      }
      public void changeChannel(int channel) {
        System.out.println(channel + "(으)로 채널조정하다.");
      } 
    }
    
  • 참조 변수의 타입으로 인터페이스를 사용할 수 있다. 이 경우 인터페이스가 가지고 있는 메소드만 사용할 수 있다.

    public class LedTvExam {
      public static void main(String[] args) {
        TV tv = new LedTV();
          
        tv.turnOn();
        tv.changeVolume(50);
        tv.changeChannel(6);
        tv.turnOff();
      }
    }
    
  • 상속과 구현을 동시에 할 수도 있다.

    public class 클래스명 extends 상위클래스명 implements 인터페이스명 { ... }
    
  • 동일한 인터페이스를 구현한다는 것은 클래스 사용법이 같다는 것을 의미한다.
    • TV 인터페이스를 구현하는 LcdTV, OledTV 등을 생성했을 때, LedTV와 동일한 기능을 가진다.
  • 💡 인터페이스가 가지고 있는 모든 추상 메소드를 구현하지 않는다면, 해당 클래스는 추상 클래스가 된다.
    • abstract 키워드를 사용하여 추상 클래스로 선언해야 한다.

인터페이스를 이용한 다중 상속

  • 클래스는 인터페이스를 여러 개 구현할 수 있다.

    interface Animal { ... }
    interface Pet { ... }
      
    // 2개의 인터페이스를 동시에 구현
    class Cat implements Animal, Pet { ... }
    
  • 자식 클래스가 여러 부모 클래스를 상속받는 다중 상속을 할 경우 메소드 출처의 모호성 등 여러가지 문제 발생 가능성 때문에 자바에서는 클래스를 통한 다중 상속을 지원하지 않는다.

    class Animal { public void cry() {...} }
      
    // 상속받은 메소드 오버라이딩
    class Cat extends Animal { public void cry() {...} } 
    class Dog extends Animal { public void cry() {...} }
      
    class MyPet extends Cat, Dog {}
    
    • Cat 클래스와 Dog 클래스는 Animal 클래스를 상속받아 cry() 메소드를 오버라이딩하고 있다.
    • MyPet 클래스가 Cat과 Dog 클래스를 다중 상속받게 되면서, MyPet 인스턴스가 cry() 메소드를 호출할 경우 어느 클래스에서 상속받은 메소드인지 구분할 수 없는 모호성을 지니게 된다.
  • 하지만, 인터페이스를 다중 상속하게 되면 메소드 호출의 모호성을 방지할 수 있다.

    interface Animal { public abstract void cry(); }
      
    // 인터페이스를 상속받는 인터페이스
    interface Cat extends Animal { public abstract void cry(); } 
    interface Dog extends Animal { public abstract void cry(); }
      
    // 상속받은 메소드 정의
    class MyPet implement Cat, Dog { public void cry() {...} }
    
    • 인터페이스에서는 메소드 구현부를 작성하지 않고, Cat, Dog 인터페이스를 구현한 MyPet 클래스에서만 cry() 메소드를 정의하므로 앞에서 발생한 메소드 호출의 모호성이 없다.
    • 💡 인터페이스는 인터페이스로부터만 상속을 받을 수 있으며, 여러 인터페이스를 상속받을 수도 있다.

인터페이스의 default method와 static method

  • JAVA 8이 등장하면서 interface에 대한 정의 몇 가지가 변경되었다.
    • default methodstatic method 정의 가능
  • 인터페이스 내 메소드가 default 혹은 static 키워드로 선언되면, 메소드를 정의할 수 있다.
  • 또한, 이를 구현하는 클래스는 default 메소드를 오버라이딩할 수 있다.
  • 인터페이스가 변경되면 인터페이스를 구현하는 모든 클래스들이 해당 메소드를 구현해야 하는 문제가 있다. 이런 문제를 해결하기 위해 인터페이스에 메소드를 구현해놓을 수 있도록 했다.

    public interface Calculator {
      
      public int plus(int i, int j);
      public int multiple(int i, int j);
        
      // default 키워드를 이용하여 메소드 구현이 가능
      default int exec(int i, int j) { 
        return i + j;
      }
    }
      
    // Calculator 인터페이스를 구현하는 클래스
    public class MyCalculator implements Calculator {
        
      @Override
      public int plus(int i, int j) {
        return i + j;
      }
        
      @Override
      public int multiple(int i , int j) {
        return i * j;
      }
    }
      
    public class MyCalculatorExam {
      
      public static void main(String[] args) {
        
        Calculator cal = new MyCalculator(); // 인터페이스 타입으로 참조
        cal.plus(3, 4);
        int value = cal.exec(5, 10); // 인터페이스에서 구현한 default 메소드 사용
          
        System.out.println(value);
      }
    }
    
  • static 메소드
    • 인터페이스에 static 메소드를 선언함으로써, 인터페이스를 이용하여 간단한 기능을 가지는 유틸리성 인터페이스를 만들 수 있게 되었다.
    • 인터페이스에서 정의한 static 메소드는 반드시 인터페이스명.메소드명() 형식으로 호출해야 한다.
    public interface Calculator {
      
      public static int exec2(int i, int j) { // static 메소드
        return i * j;
      }
    }
      
    public class MyCalculatorExam {
      
      public static void main(String[] args) {
          
        int value2 = Calculator.exec2(5, 10); // '인터페이스명.메소드명()' 형식으로 호출
        System.out.println(value2);
      }
    }
      
    

출처