2023. 6. 15. 16:42ㆍJava/객체지향
1. 인터페이스란? (Interface)
- 인터페이스는 일종의 추상클래스.
- 단, 추상클래스보다 추상화정도가 높다.
추상클래스는 추상메서드를 하나라도 가지고있으면 추상클래스이고 일반 메서드와 멤버변수를 가질 수 있지만,
인터페이스는 오직 추상메서드와 상수만을 멤버로 가질 수 있고 그 외에는 다른 어떠한 요소도 허용하지 않는다.
- 추상클래스가 '미완성 설계도' 라면, 인터페이스는 '기본 설계도' 라고 할 수 있다.
그러므로 주로 다른 클래스를 작성하는데 도움을 주는 목적으로 사용된다.
2. 인터페이스의 작성
interface 인터페이스이름 {
public static final 타입 상수이름 = 값;
public abstract 메서드이름 (매개변수목록);
}
- 인터페이스는 작성하는 것은 클래스를 작성하는 것과 같지만 키워드로 'interface'를 사용한다
- 인터페이스 멤버들의 제약사항
1) 모든 멤버변수는 public static final이어야 하며, 이를 생략할 수 있다.
2) 모든 메서드는 public abstract이어야 하며, 이를 생략할 수 있다.
(JDK1.8부터 static메서드와 디폴트 메서드 제외)
3. 인터페이스의 상속
- 인터페이스는 인터페이스로부터만 상속받을 수 있으며
- 클래스와 달리 다중상속이 가능하다.
즉, 여러 개의 인터페이스로부터 상속을 받는 것이 가능하다.
- 인터페이스는 클래스와 달리 Object와 같은 최고 조상이 없다.
4. 인터페이스의 구현
class 클래스이름 implements 인터페이스이름 {
//인터페이스에 정의된 추상메서드를 구현해야 함
}
- 인터페이스도 추상클래스처럼 당연히 그 자체로는 인스턴스를 생성할 수 없다.
- 추상클래스가 상속을 통해 추상메서드를 완성하는 것 처럼,
인터페이스도 자신에 정의된 추상메서드의 몸통을 만들어주는 '클래스'를 작성해야한다.
- 추상클래스는 자신을 상속받는 클래스를 정의할 때 확장한다는 의미의 키워드 extends를 사용하지만
인터페이스는 구현한다는 의미의 키워드 'implements'를 사용한다.
- 상속과 구현을 동시에 할 수도 있다
class Fighter extends Unit implements Fightable {
//추상클래스 Unit의 추상메서드 구현
//인터페이스 Fightable의 추상메서드 구현
}
5. 인터페이스를 이용한 다중상속
- 자바와 다중상속
두 조상으로부터 상속받는 멤버 중에서
멤버변수의 이름이 같거나, 메서드의 선언부가 일치하고 구현 내용이 다르면
이 두 조상으로부터 상속받는 자손클래스는 어느 조상의 것을 상속받게 되는 것인지 알 수 없다.
어느 한 쪽으로부터의 상속을 포기하거나, 이름이 충돌되지 않도록 조상클래스를 변경해야한다.
그래서 다중상속은 장점도 있지만 단점이 더 크기 때문에 자바는 다중상속을 허용하지 않는다.
인터페이스를 사용하면 다중상속을 사용할 수 있다고 말하지만 자바로 인터페이스를 구현하는 경우는 거의 없다.
- 만일 두 개의 클래스로부터 상속을 받아야 할 상황이라면,
두 조상 클래스 중 비중이 높은 쪽을 선택하고 다른 한 쪽은 클래스 내부에 멤버로 포함시키는 방식으로 처리하거나
어느 한쪽의 필요한 부분을 뽑아서 인터페이스로 만든 후 구현하도록 한다.
6. 인터페이스를 이용한 다형성
- 인터페이스 역시 해당 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있으며,
인터페이스 타입으로의 형변환도 가능하다.
-인터페이스 Fightable을 클래스 Fighter가 구현했을 때,
Fighter인스턴스가 Fightable타입의 참조변수로 참조하는 것이 가능하다.
- 리턴타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구한한 클래스의 인스턴스를 반환한다는 것을 의미
7. 인터페이스의 장점
- 개발시간을 단축시킬 수 있다.
- 표준화가 가능하다.
- 서로 관계없는 클래스들에게 관계를 맺어줄 수 있다.
- 독립적인 프로그래밍이 가능하다.
8. 인터페이스의 이해
- 인터페이스를 이해하기 위해 염두에 두고 있어야할 두 가지 사항
1) 클래스를 사용하는 쪽(User)과 클래스를 제공하는 쪽(Provider)이 있다.
2) 메서드를 사용(호출)하는 쪽에서는 사용하려면 메서드의 선언부만 알면 된다. (내용은 알 필요 없음)
9. 디폴트 메서드와 static 메서드
원래는 인터페이스에는 추상 메서드만 선언할 수 있었지만 JDK 1.8부터
디폴트 메서드와 static 메서드도 추가할 수 있게 되었다.
1) 디폴트 메서드
- 인터페이스에 메서드가 추가되는 것과 같은 변경사항은
이 인터페이스를 구현한 기존의 모든 클래스들이 새로 추가된 메서드를 구현해야한다는 것이므로 번거롭다.
- 인터페이스가 변경되지 않으면 좋겠지만, 언젠가는 변경해야한다. 이 때문에 디폴트 메서드를 구상함.
- 디폴트 메서드는 추상 메서드의 기본적인 구현을 제공하는 메서드로,
추상 메서드가 아니기 때문에 디폴트 메서드가 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지
않아도 된다.
- 디폴트 메서드 앞에는 키워드 default를 붙이며, 일반 메서드와 같이 몸통이 있어야한다. public.
- 새로운 추가된 디폴트 메서드가 기존의 메서드와 이름이 중복되어 충돌하는 경우 해결 규칙
# 1. 여러 인터페이스의 디폴트 메서드 간의 충돌
-> 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩 해야한다.
# 2. 디폴트 메서드와 조상 클래스의 메서드 간의 충돌
-> 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.
2) static 메서드
- static 메서드는 인스턴스와 관계가 없는 독립적인 메서드이기 때문에 인터페이스에 추가하지 못할 이유가 없었음
- 예: java.util.Collection 인터페이스
이 인터페이스와 관련된 static 메서드들이 원칙때문에 별도의 Collections클래스에 들어가게 되었음
- 인터페이스의 static메서드 역시 접근 제어자가 항상 public이며, 생략가능하다.