[JAVA] 인터페이스

업데이트:



2023.06.15 내용보완

✅ 인터페이스란?

자바 개발 뿐만아니라 자바기반 개발을 하면 인터페이스는 굉장히 중요하고 빈번하게 사용된다. 인터페이스란 뭘까?

동일한 목적 하에 동일한 기능을 보장하게 하기 위함! 자바의 다형성, 추상화를 이용하여 코드 수정을 줄이고 유지보수성을 높인다!

이렇게 크게 두가지 정도로 볼 수 있다. 좀더 자세하게 알아보자.


자식 클래스가 여러 부모 클래스를 상속받을 수 있다면, 다양한 동작을 수행할 수 있다는 장점을 가질 수 있다.

하지만 클래스를 이용하여 다중 상속을 할 경우 메소드 출처의 모호성 등 여러 가지 문제가 발생할 수 있어 자바에서는 클래스를 통한 다중 상속은 지원하지 않는다.

하지만 다중 상속의 이점을 버릴 수는 없기에 자바에서는 인터페이스라는 것을 통해 다중 상속을 지원하고 있다.




인터페이스(interface)란 다른 클래스를 작성할 때 기본이 되는 틀을 제공하면서, 다른 클래스 사이의 중간 매개 역할까지 담당하는 일종의 추상 클래스를 의미한다.




자바에서 추상클래스추상메소드, 생성자, 변수, 심지어 일반 메소드(구현부 포함) 도 포함 될 수 있다. 그러나 인터페이스에서는 추상메소드, 상수, 정적 메소드, 디폴트메소드 를 포함 할 수 있다.





✅ 인터페이스 선언

인터페이스는 추상클래스와 마찬가지로 자신이 직접 인스턴스를 생성 할 수 없다. 한마디로 다른 클래스에서 객체로 생성 될 수 없다는 뜻이다. 때문에 다른 클래스에서 인터페이스를 사용하기 위해서는 다음과 같은 문법을 통해 구현한다.

public class 클래스이름 implements 인터페이스이름 {...}





✅ 인터페이스 구현

인터페이스에서 구현할 수 있는 상수, 추상메소드, 디폴트메소드, 정적메소드 4가지를 활용한 코드를 보자.

public interface CalResult {

	// 계산기에서 입력될 수 있는 최대값
	// 상수
	public static final int MAX_INTEGER = 999999999;

	// 계산 결과 출력
	// 추상 메소드
	// public abstract는 생략가능하다
	public abstract void PrintResult(double result);
	
	// 연산 과정 출력
	// 추상 메소드
	void PrintProcess(StringBuffer sb);
	

	
	// 디폴트메소드 : 인터페이스에서 기본적으로 제공해주지만, 
	// 각자 구현해서 쓸수 있다. (선택적)
	default void Display(StringBuffer sb, double result){
		PrintProcess(sb);
		PrintResult(result);
		PrintFinish();
	}
	
	// 정적메소드 : 인터페이스에서 제공해주는 것으로 무조건 사용 ( 절대적 )
	static void PrintFinish(){
		System.out.println("계산끝났당오예~!");
	}
}


  • 상수 : 인터페이스에서 값을 정해줄테니 함부로 바꾸지 말고 제공해주는 값만 참조하라 (절대적)

  • 추상메소드 : 가이드만 줄테니 추상메소드를 오버라이딩해서 재구현해라 (강제적)

  • 디폴트메소드 : 인터페이스에서 기본적으로 제공해주지만, 각자 구현해서 쓸수 있다. (선택적)

  • 정적메소드 : 인터페이스에서 제공해주는 있는 그대로 사용. 즉 오버라이딩 불가 (절대적)




📌 상수

인터페이스에서 선언한 상수는 항상 public static final 형태로 저장되므로 다른 클래스에서 변경 할 수 없다. 위에 (절대적)이라고 써놓은 이유이다. 그러나 자료를 찾아보니 인터페이스에서 상수를 선언하는 것은 Anti-Pattern, 즉 사용을 지양해야하는 디자인 패턴 이라는 주장이 많았다. 되도록 사용하지 않는게 좋아보인다.



📌추상메소드

추상클래스의 추상메소드와 같다. 접근제어자 abstract 반환 타입 클래스명 (자료형 변수명); 의 형태로 선언하면 된다. 예를들면 public abstract void Print(String str) 이런식으로 선언할 수 있다. 이때 접근제어자와 abstract는 생략 가능하다.

추상메소드는 구현부는 따로 설정하지 않고 상속받은 클래스에서 오버라이딩해서 사용하도록 한다. 이때, 추상클래스든 인터페이스든 선언된 추상메소드는 반드시 오버라이딩을 통해 재구현 되어야만 한다! 위에 (강제적) 이라고 써놓은 이유이다.



📌디폴트메소드

원래 인터페이스에서는 추상메소드와 상수만 사용해서 제약을 많이 걸어뒀지만 JAVA8부터 디폴트메소드와 정적메소드를 추가하여 인터페이스의 범용성을 높였다.

디폴트 메소드는 default 접근제어자 메소드명 ( 자료형 변수명 ); 의 형태로 선언한다. 디폴트 메소드는 상속받은 클래스에서 반드시 사용할 필요는 없다. 필요에 따라 사용유무를 결정하면 된다.


디폴트 메소드를 쓰는 경우의 예시를 들어보자. 내가 사칙연산 기능만 가지고 있는 계산기 프로그램을 만들어서 A,B,C 라는 사람에게 배포했다고 치자. 그런데 A라는 사람이 사칙연산 뿐만 아니라 공학용 계산기를 만들어달라고 한다. 공학용 계산기를 처음부터 다시 만드는건 어려우니 기존 사칙연산 계산기에 공학용 기능을 추가해서 배포하려고 한다.

이때 인터페이스에 추상메소드로 공학용 기능을 추가해서 배포하면 공학용 기능이 필요하지 않은 B,C도 공학용 메소드를 반드시 오버라이딩 해야 하는 불필요한 작업이 추가된다. 때문에 공학용 메소드를 디폴트 메소드로 정의하면 A만 따로 메소드를 추가해서 사용할 수 있는 이점이 생긴다. 이런 이유로 위에 (선택적) 이라고 적어놓은 것이다.




📌정적 메소드

인터페이스에서 제공한 메소드 그대로 사용해야만 한다. static 접근제어자 클래스명 (자료형 변수명) 형태로 사용한다. 반드시 써야하는 메소드는 아니고 필요에 따라 선언하면 된다.





✅ 인터페이스의 장점

  1. 대규모 프로젝트 개발 시 일관되고 정형화된 개발을 위한 표준화가 가능하다. -> 객체지향의 다형성
  2. 클래스의 작성과 인터페이스의 구현을 동시에 진행할 수 있으므로, 개발시간을 단축할 수 있다.
  3. 클래스와 클래스 간의 관계를 인터페이스로 연결하면, 클래스마다 상속구조 없이 독립적인 프로그래밍이 가능하다.

댓글남기기