Backend/Java

Java 인터페이스(Interface)

가은파파 2021. 3. 6. 00:51

목표

자바의 인터페이스에 대해 학습하세요.

학습할 것 (필수)

  • 인터페이스 정의하는 방법
  • 인터페이스 구현하는 방법
  • 인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
  • 인터페이스 상속
  • 인터페이스의 기본 메소드 (Default Method), 자바 8
  • 인터페이스의 static 메소드, 자바 8
  • 인터페이스의 private 메소드, 자바 9

인터페이스 정의하는 방법

자바의 인터페이스

- 인터페이스는 추상 메서드의 집합이다. (static,디폴트 메서드, 상수 도 포함되지만 중요하지 않음)

- 자바에서의 인터페이스는 기본적으로 무언가를 규제하기 위한 것이다.

 

추상클래스는 일반클래스, 일반 메서드를 가질 수도 있다. but 인터페이스는 추상메서드만의 집합이다.

 

정의하는 방법

- 값이 들어갈 수 있고, 메소드는 실제 구현이 들어가진 않고, 상속받는 실제 클래스에서 구현할 뼈대가 필요하다.

- 구현된 것이 전혀 없는 설계도. 껍데기

- 모든 멤버가 public (그러나 생략되어 있다)

- 상수도 항상 static이고 final이다. (생략 가능)

interface Calculable{
    double PI = 3.14;
    int sum(int v1, int v2);
}
interface Printable{
    void print();
}

인터페이스 구현하는 방법

인터페이스의 구현(implements) : 인터페이스에 정의된 추상 메서드를 완성하는 것.

- 아래 샘플을 통해 구현하는 방법을 볼 수 있다.

interface Calculable{
    double PI = 3.14;
    int sum(int v1, int v2);
}
interface Printable{
    void print();
}
class RealCal implements Calculable, Printable{
    public int sum(int v1, int v2) {
        return v1+v2;
    }
    public void print() {
        System.out.println("This is RealCal!!");
    }
}

인터페이스 레퍼런스를 통해 구현체를 사용하는 방법

- 인터페이스의 다형성을 활용해 레퍼런스 타입으로 구현체의 사용을 제한시킬 수 있다.

- 아래 샘플 InterfaceApp에서 Printable의 레퍼런스 타입으로 클래스를 생성시에 해당 변수의 레퍼런스 타입을 Printable 인터페이스로 지정을 하면 print()만 사용가능하고 sum기능은 사용을 제한시킬 수 있다.

interface Calculable{
    double PI = 3.14;
    int sum(int v1, int v2);
}
interface Printable{
    void print();
}
class RealCal implements Calculable, Printable{
    public int sum(int v1, int v2) {
        return v1+v2;
    }
    public void print() {
        System.out.println("This is RealCal!!");
    }
}
class AdvancedPrint implements Printable{
    public void print() {
        System.out.println("This is RealCal!!");
    }
}
public class InterfaceApp {
    public static void main(String[] args) {
        Printable c = new AdvancedPrint();
        c.print();
    }
}

- 일부만 구현하는 경우, 클래스 앞에 abstract를 붙여야 한다.

interface Fightable{ 
 public move(int x, int y);
 public attack(int z);
}

abstract class Fighter implements Fightable {
	public void move(int x, int y) { /* 내용 생략 */ }
}

인터페이스 상속

- 하나의 클래스는 여러개의 인터페이스를 받을 쓸 수 있다. (다중 상속)

- 인터페이스의 조상은 인터페이스만 가능(Object가 최고 조상 아님)

interface Calculable{
    double PI = 3.14;
    int sum(int v1, int v2);
}
interface Printable{
    void print();
}
class RealCal implements Calculable, Printable{
    public int sum(int v1, int v2) {
        return v1+v2;
    }
    public void print() {
        System.out.println("This is RealCal!!");
    }
}

인터페이스의 장점

 

두 대상(객체) 간의 연결,대화,소통을 돕는 '중간 역할'을 한다.

선언(설계)와 구현을 분리시킬 수 있게 한다.

인터페이스 덕분에 B가 변경되어도 A는 안바꿀 수 있게 된다.(느슨한 결합)

- A는 껍데기인 인터페이스와만 결합되있기 때문이다.

개발 시간을 단축할 수 있다.

변경에 유리한 유연한 설계가 가능하다.

표준화가 가능하다. (ex. JDBC : 인터페이스들의 집합)

서로 관계없는 클래스들을 관계를 맺어줄 수 있다.


인터페이스의 기본 메소드 (Default Method), 자바 8

기존에는 추상메소드의 집합을 인터페이스라고 썼지만 자바 8부터 디폴트 메서드가 추가되었다. 

 

why?

인터페이스에 새로운 메서드(추상 메서드)를 추가하기 어려움. 왜냐하면 기존에 구현됬던 메서드들에 추상메서드 하나를 추가하므로서 많은 구현작업이 필요하다. 그래서 디폴트 메서드가 추가하였다.

 

그렇지만 디폴트 메서드도 인터페이스를 상속받아서 오버라이딩이 가능하다. 그러나 optional이다.

 

interface MyInterface {
  void method();
   void newMethod();
}

interface MyInterface {
  void method();
  default void newMethod() {}; //디폴트 메서드 추가
}

인터페이스의 static 메소드, 자바 8

디폴트 메서드와 마찬가지로 자바 8에서 static 메서드의 수요에 의해 추가되었다.

 

static메서드가 추가된 인터페이스를 상속받아도 static 특징상 재정의(오버라이딩) 불가능하다. 아래 샘플처럼 static 메소드는 호출만 가능하다.

 

public interface Calculator {
  public int plus(int pre, int post);
  public int multi(int pre, int post);
  default int execPlus(int pre, int post){ return pre + post; }
  static int execMulti(int pre, int post){ return pre * post; }
}

public class CalculatorImpl implements Calculator {

	@Override
	public int plus(int pre, int post) {
		return pre + post;
	}

	@Override
	public int multi(int pre, int post) {
		return pre * post;
	}
	
}

public class InterfaceEx {

	public static void main(String[] args) {
		Calculator cal = new CalculatorImpl();
		int resultPlus = cal.plus(3, 9);
		int resultMulti = cal.multi(3, 9);
		System.out.println("resultPlus 값은 : " + resultPlus);
		System.out.println("resultMulti 값은 : " + resultMulti);
		
		int resultExecPlus = cal.execPlus(3, 9);
		System.out.println("dafault method 호출 결과 : " + resultExecPlus);
		
		int resultExecMulti = Calculator.execMulti(3, 9); //static 메소드는 호출만 가능하다.
		System.out.println("static method 호출 결과 : " + resultExecMulti);
	}
}

인터페이스의 private 메소드, 자바 9

자바9 부터 Private methods , Private Static methdos 까지 추가되었습니다. 이제 인터페이스에서 implementation(구현)을 포함 시킬 수 있습니다.
private 는 클래스 내부적으로만 볼 수 있기 때문에 복잡한 메소드를 작성하는 것이 좋고, 코드의 재사용, 유지 및 이해하기가 더 쉽습니다. 

public interface Calc {
	
	double PI = 3.14; //나중에 상수가됨
	int ERROR = -9999999;
	
	int add(int num1, int num2);
	int substract(int num1, int num2);
	int times(int num1, int num2);
	int divide(int num1, int num2);
	//디폴트 메서드
	default void description() {
		System.out.println("정수 계산기를 구현합니다.");
		myMethod(); //private 메서드 사용
	}
	//static메서드
	static int total(int[] arr) {
		int total = 0;
		
		for(int i :arr) {
			total+= i;
		}
		mystaticMethod();//private static 메서드 사용
		return total;
	}
	//private 메서드
	private void myMethod() {
			System.out.println("private method");
}
	//private static 메서드
	private static void mystaticMethod() {
		System.out.println("private static method");
	}

}
  • private 메서드 myMethod는 인터페이스 내에서만 사용가능한 메서드로 description()안에 사용되었습니다.

  • private static 메서드는 인터페이스 내에서만 사용가능하고 static 키워드가 있기에 static 메서드안에서만 사용가능하기 때문에 total에 사용되었습니다.

 

출처