Java

[Java] 인터페이스(interface) - 특징, 구현 방법, 상속, 다형성, 장점, 디폴트 메서드

Hyeonni 2022. 8. 26. 18:28

 인터페이스(interface)란?

 

인터페이스는 일종의 추상 클래스이다. 그러나 일반 추상클래스는 멤버 변수와 일반 메서드를 가질 수 있는 반면 인터페이스는 추상 클래스보다 추상화 정도가 높아 일반 메서드와 일반적인 멤버 변수를 가질 수 없다는 특징이 있다. 즉, 인터페이스는 상수와 추상메서드만 가질 수 있다.

 

 

 인터페이스 작성 방법

 

  • class 키워드 대신 interface 사용
  • interface도 class와 같이 접근제어자로 public과 default를 사용할 수 있다.
  • 모든 멤버변수는 상수로 제어자가 'public static final' 이어야만 한다. => 제어자 생략 가능
  • 모든 메서드의 제어자는 'public abstract' 이어야 한다. => 제어자 생략 가능 
    • JDK 1.8 버전부터 static 메서드와 디폴트 메서드도 만들 수 있다. (아래 자세히 설명)
  • 인터페이스의 이름을 지을 때 '~able'을 붙이는 경우가 많다.
interface interfaceName{
	public static final 타입 varName;
    //== 타입 varName;
    
  	public abstract 리턴형 methodName(매개변수 목록);
    //== 리턴형 methodName(매개변수 목록);
}

 

 

 인터페이스 상속

 

  • 인터페이스는 인터페이스로부터만 상속받을 수 있다.
  • 클래스와는 달리 다중 상속이 가능하다.
    • 인터페이스는 Object 클래스와 같은 최고 조상 클래스는 없다.

 

 

인터페이스 구현

 

  • implements 키워드를 사용하여 인터페이스 내의 메서드들을 구현한다.
class 클래스명 implements 인터페이스명 {
	//인터페이스에 정의된 추상메서드 구현
}

//구현하는 인터페이스의 메서드 중 일부만 구현하는 경우, abstract를 사용해 추상클래스로 선언
abstract class 클래스명 implements 인터페이스명 {
	//인터페이스에 정의된 추상메서드 구현
}

//상속과 동시 사용 가능
class 클래스명 extends 상속클래스명 implements 인터페이스명 {
	//인터페이스에 정의된 추상메서드 구현
}

 

  • 인터페이스를 오버라이딩 할 때, 상위 메서드보다 넓은 범위의 접근 제어자를 지정해야 하므로 무조건 public으로 지정해야 한다.
    • 인터페이스의 추상 메서드는 public abstract 가 기본이기 때문이다. 

 

인터페이스 사용법

 

자바는 class 다중 상속을 지원하지 않기 때문에 인터페이스를 이용해서 다중 상속하는 것처럼 사용한다.

두 개의 class를 상속하려고 한다면 중요도가 더 높은 클래스는 바로 상속을 하고, 남은 클래스는 인터페이스로 만든 다음 하위 클래스에 해당 클래스의 인스턴스를 생성하고 인터페이스 내의 메서드를 구현할 때, 생성한 인스턴스의 메소드를 호출하는 방식으로 작성하는 것이다.

물론 상속받을 클래스의 인스턴스를 생성하는 방식으로만 작성해도 충분하지만 인터페이스를 이용하면 다형성 측면에서 이점이 있다.

public class VCR{
	public void play{
    	//실행 내용
    }
}

//IVCR은 VCR 내의 메서드들을 추상메서드로 바꾼 인터페이스
public interface IVCR {
	public void play();
}

public class TVCR extends Tv implements IVCR {
	Vcr vcr = new VCR();
    
    public void play() {
    	vcr.play();
    }
}

 

 

인터페이스를 이용한 다형성

 

  • 인터페이스 타입의 참조 변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있다.
  • 인터페이스 타입으로 형 변환도 가능하다.
  • 인터페이스를 메서드의 매개변수 타입으로 사용할 수 있다. 
    • 메서드 호출 시 해당 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야 한다는 의미이다.
  • 인터페이스를 메서드의 리턴 타입으로 지정할 수 있다.
    • 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.

 

 

인터페이스의 장점

 

1. 개발 시간이 단축된다.- 메서드를 호출하는 쪽에서 메서드의 내용에 관계없이 선언 부만 알면 된다. (캡슐화)

 

2. 표준화가 가능하다.

 

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

 

4. 독립적인 프로그래밍이 가능하다.- 인터페이스를 이용하면 클래스의 선언과 구현을 분리시킬 수 있기 때문에 실제 구현에 독립적인 프로그램을 작성하는 것이 가능하다. 클래스와 클래스 간의 직접적인 관계를 인터페이스를 이용해서 간접적인 관계로 변경하면, 한 클래스의 변경이 관련된 다른 클래스에 영향을 미치지 않는 독립적인 프로그래밍이 가능하다.

 

 

- 클래스를 사용하는 쪽(user)과 클래스를 제공하는 쪽(provider)이 있다.
- 메서드를 호출하는 user에서는 사용하려는 메서드(provider)의 선언 부만 알면 된다. (구현 내용은 몰라도 된다.)

 

클래스 A와 클래스 B가 있다면 A의 메서드에서 매개변수로 클래스 B를 선언했다. 이 경우 두 클래스(A-B)는 직접적인 관계에 놓이게 되므로 클래스 B에 변경이 발생한다면 클래스 A 또한 B로 인한 변경이 발생할 가능성이 매우 높아진다.

그렇기 때문에 인터페이스를 사용하여 클래스 B를 인터페이스로 만들고 클래스 A에서 매개변수로 인터페이스를 사용하게 된다면 A-I-B의 간접적인 관계가 되어 위와 같은 위험을 방지할 수 있다.

 

추가적으로 알아두어야 할 것은 인터페이스 또한 Object 클래스에 정의된 메서드를 가지고 있다.

Object 클래스는 모든 객체가 상속하고 있다.

 

 

static 메서드 & default(디폴트) 메서드

 

static 메서드와 디폴트 메서드는 JDK 1.8에서부터 인터페이스 내에 정의할 수 있다.

static 메서드의 경우, 인스턴스에 독립적인 메서드이기 때문에 인터페이스에 추가하는데 문제가 되지 않는다.

 

그러나 디폴트 메서드의 경우는 선언과 정의가 완료된 일반 메서드라고 볼 수 있다.

이미 구성이 완료된 인터페이스에 필요한 메서드가 생겨 추가가 된다면 인터페이스를 구현한 모든 클래스에서 새로 추가된 메서드를 구현해야만 하는 문제가 발생한다. 이런 경우로 인해 생겨난 게 디폴트 메서드이다.

리턴형 앞에 default 키워드를 붙여서 사용한다.

 

디폴트 메서드로 인해 메서드 간에 이름 중복이 일어나는 경우 해결하는 규칙은 아래와 같다.

  • 여러 인터페이스의 디폴트 메서드 간의 충돌
    • 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩 해야 한다.
  •  디폴트 메서드와 조상 클래스의 메서드 간의 충돌
    • 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.

 

 

 

더보기

출처 : 자바의 정석 (남궁성)