7.7 인터페이스(interface)

jungnoeun·2022년 5월 24일
0

java

목록 보기
13/22

7.1 인터페이스란?

인터페이스는 일종의 추상클래스이다. 추상클래스처럼 추상메서드를 갖지만 추상클래스보다 추상화 정도가 높아서 추상클래스와 달리 몸토을 갖춘 일반 메서드 또는 멤버변수를 구성원으로 가질 수 없다.
오직 추상메서드와 상수만을 멤버로 가질 수 있다.
추상 클래스를 부분적으로만 완성된 '미완성 설계도'라고 한다면, 인터페이스는 구현된것은 아무것도 없고 밑그림만 그려져있는 '기본 설계도'라고 할 수 있다.






7.2 인터페이스의 작성

  • 인터페이스를 작성하는 방법은 클래스와 같지만 키워드를 class가 아닌 interface를 사용한다.
  • 접근제어자로 public 또는 default를 사용할 수 있다.
interface 인터페이스이름 {
	public static final 타입 상수이름 =;
	public abstract 메서드이름(매개변수목록);
}

일반 클래스의 멤버들과 달리 인터페이스의 멤버들은 다음과 같은 제약사항이 있다.

  • 모든 멤버변수는 public static final이어야 하며, 이를 생략할 수 있다.
  • 모든 메서드는 public abstract이어야 하며, 이를 생략할 수 있다.
    (단, static메서드와 디폴트 메서드는 jdk1.8이후로는 사용가능하다.)
  • 이러한 제어자는 생략가능하며, 생략한 제어자는 컴파일시에 컴파일러가 자동적으로 추가해준다.






7.3 인터페이스의 상속

  • 인터페이스는 인터페이스로부터만 상속받을 수 있다.
  • 클래스와 달리 다중상속이 가능하다.
  • 클래스의 상속과 마찬가지로 자손 인터페이스는 조상 인터페이스에 정의된 멤버를 모두 상속받는다.






7.4 인터페이스의 구현

인터페이스는 추상클래스처럼 그 자체로 인스턴스를 생성할 수 없다. 그래서 인터페이스에 정의된 추상메서드의 몸통을 만들어주는 클래스를 작성해야 한다. 이때 구현한다는 의미의 키워드 'implements' 를 사용한다.

  • 만약 구현하는 인터페이스의 메서드 중 일부만 구현한다면, abstract를 붙여서 추상클래스로 선언해야 한다.
  • 상속과 구현을 동시에 할 수 있다.
//인터페이스 구현 형식
class 클래스이름 implements 인터페이스이름 {
	//인터페이스에 정의된 추상메서드를 구현해야 한다.
}

//상속과 구현을 동시에 하는 예시
class Fighter extends Unit implements FIghtable {
	public void move(int x, int y) { /*내용생략*/ }
	public void attack(Unit u)	{ /*내용생략*/ }
}

조상 인터페이스에 있는 메서드를 자손 인터페이스를 구현하는 클래스에서 오버라이딩할 때 조상의 메서드보다 넓은 범위의 접근제어자를 지정해야 한다.






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

인터페이스는 static상수만 정의할 수 있으므로 조상클래스의 멤버변수와 충돌하는 경우는 겨의 없고 충돌된다하더라도 클래스의 이름을 붙여서 구분이 가능하다. 그리고 추상메서드는 구현내용이 전혀 없으므로 조상클래스의 메서드와 선언부가 일치하는 경우에는 당연히 조상클래스쪽의 메서드를 상속받으면 되므로 문제되지 않는다.
하지만, 이렇게 하면 상속받는 멤버의 충돌은 피할 수 있지만, 다중상속의 장점을 잃게 된다. 만일 두개의 클래스로부터 상속을 받아야 할 상황이라면, 두 조상클래스 중에서 비중이 높은 쪽을 선택하고 다른 한쪽은 클래스 내부에 멤버로 포함시키는 방식으로 처리하거나 어느 한쪽의 필요한 부분을 뽑아서 인터페이스로 만든 다음 구현하도록 한다.






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

인터페이스는 이를 구현한 클래스의 조상이라 할 수 있으므로 해당 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있으며, 인터페이스 타입으로의 형변환도 가능하다.

Fightable f = (Fightable)new Fighter();
	또는
Fightable f = new Fighter();



  • 인터페이스는 메서드의 매개변수 타입으로도 사용가능하다.
void attack(Fightable f) {
	//....
}

그래서 attack메서드를 호출할 떄는 매개변수로 Fightable인터페이스를 구현한 클래스의 인스턴스를 넘겨줘야 한다.



  • 메서드의 리턴타입으로 인터페이스의 타입을 지정하는 것도 가능하다.
Fightable method() {
	...
	Fighter f = new Fighter();
	return f;
}

리턴타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.
위의 코드에서는 method()의 리턴타입이 Fightable인터페이스이기 때문에 메서드의 return문에서 Fightable인터페이스를 구현한 Fighter클래스의 인스턴스를 반환한다.






7.7 인터페이스의 장점

인터페이스를 사용하는 이유와 장점

  • 개발 시간을 단축시킬 수 있다.
  • 표준화가 가능하다.
  • 서로 관계없는 클래스들에게 관계를 맺어줄 수 있다.
  • 독립적인 프로그래밍이 가능하다.





7.8 인터페이스의 이해

인터페이스의 기본 사항

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






디폴트 메서드와 static 메서드

원래 인터페이스에 추상메서드만 선언할 수 있는데 jdk1.8부터 디폴트 메서드와 static메서드도 추가할 수 있게 되었다.

  • 인터페이스의 static메서드는 접근 제어자가 항상 public이며, 생략가능하다.
  • 디폴트 메서드는 추상 메서드의 기본적인 구현을 제공하는 메서드로, 추상 메서드가 아니기 때문에 디폴트 메서드가 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 된다.
  • 디폴트 메서드는 앞에 키워드 default를 붙이며, 추상메서드와 달리 일반 메서드처럼 몸통{}이 있어야 한다. 디폴트 메서드 역시 접근 제어자가 public이며 생략가능하다.

새로 추가된 디폴트 메서드가 기존의 메서드와 이름이 중복되어 충돌하는 경우의 규칙
1. 여러 인터페이스의 디폴트 메서드간의 충돌
-> 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩해야 한다.
2. 디폴트 메서드와 조상 클래스의 메서드 간의 충돌
-> 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.

  • 위의 규칙들이 귀찮으면, 그냥 필요한 쪽의 메서드와 같은 내용으로 오버라이딩 해버리면 된다.
profile
개발자

0개의 댓글