https://github.com/whiteship/live-study
백기선님 자바 기초 스터디 8주차
목표
자바의 인터페이스에 대해 학습하세요.
학습할 것
- 인터페이스 정의하는 방법
- 인터페이스 구현하는 방법
- 인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
- 인터페이스 상속
- 인터페이스의 기본 메소드 (Default Method), 자바 8
- 인터페이스의 static 메소드, 자바 8
- 인터페이스의 private 메소드, 자바 9
인터페이스 정의하는 방법
인터페이스는 추상클래스처럼 추상메서드를 갖는다. 그러나 인터페이스는 일반 메서드 혹은 멤버변수를 구성원으로 가질 수 없고, 오직 추상메서드와 상수만을 멤버로 가질 수 있다는 점이 추상클래스와의 차이점이다.
즉, 인터페이스는 자체만으로 사용되기 보다는 다른 클래스를 작성하는데 도움을 줄 기본 설계도 목적으로 작성된다.
인터페이스를 정의하는 것은 클래스를 정의하는 것과 비슷하다.
interface 인터페이스 이름 {
멤버변수
...
메서드
...
}
일반적인 클래스의 멤버들과 달리 인터페이스의 멤버들은 다음과 같은 제약사항이 있다.
- 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다.
- 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다. (단, JDK 1.8부터 인터페이스에 static 메서드 정의를 허용했다)
즉, 인터페이스의 멤버변수나 메서드에 따로 타입을 정의하지 않아도, 멤버변수는 상수로, 메서드는 추상메서드로 컴파일러가 자동으로 접근지시자를 추가해준다.
+) 인터페이스에서 상수는 네임스페이스 오염 등의 문제로 인해 현재 Anti-Pattern이라는 의견이 많다. 인터페이스에는 가급적 메서드만을 사용하는 것이 좋겠다.
인터페이스 구현하는 방법
인터페이스는 추상클래스처럼 그 자체로는 인스턴스를 생성할 수 없고, 클래스 상속처럼 인터페이스를 의존하는 클래스를 정의해야 한다.
이 때, 상속의 'extends'가 아닌 구현한다는 의미의 키워드 'implements'를 사용한다.
인터페이스를 implements 했다면 그 안에 인터페이스에 정의된 메서드들을 반드시 구현해야 한다.
(인터페이스에서의 static, private 메서드들에 대해서는 뒤에서 다루겠다. 일단 일반적인 public abstract 메서드라고 생각하자)
class 클래스이름 implements 인터페이스이름 {
//인터페이스에 정의된 추상메서드를 구현해야 한다.
}
인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
상속에서 자식클래스의 인스턴스를 부모타입의 참조변수로 참조하는 것이 가능한 것처럼,
인터페이스 역시 이를 구현한 클래스의 조상이라 할 수 있으므로 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있다.
예를 들어 Fightable을 클래스 Fighter가 구현했을 때, 다음과 같이 Fighter인스턴스를 Fightable타입의 참조변수로 참조하는 것이 가능하다.
Fightable f = new Fighter();
이러한 다형성은 메서드의 매개변수 혹은 리턴 타입으로 활용할 수 있다.
void attack(Fightable f) { } //인터페이스 - 매개변수
Fightable method() { return new Fighter(); } //인터페이스 - 리턴타입
만약 리턴타입이 인터페이스라면 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.
인터페이스 상속
인터페이스끼리도 상속이 가능하다. 클래스와는 달리 다중상속이 가능하기 때문에 한 인터페이스에서, 여러 개의 인터페이스의 멤버들을 상속 받는 것이 가능하다.
interface 인터페이스 extends 인터페이스1, 인터페이스2 { }
인터페이스의 기본 메소드 (Default Method), 자바 8
원래 인터페이스에 추상 메서드만 선언할 수 있는데, JDK 1.8부터 기본 메서드와 static 메서드도 추가할 수 있게 되었다.
인터페이스에 새로운 메서드를 추가하는 것은 보통 큰 일이 아니다. 이는 인터페이스를 구현한 기존의 모든 클래스들이 새로 추가된 메서드를 구현해야하기 때문이다.
그래서 JDK 개발자들은 기본 메서드(default method)라는 것을 고안해 내었다.
기본 메서드는 기본적인 구현을 제공하는 메서드로, 쉽게 말하면 인터페이스 자체의 메서드라고 볼 수 있다.
즉, 인터페이스를 구현하는 클래스에서 기본 메서드를 굳이 오버라이딩하지 않아도 되는 것이다.
interface Myinterface {
void method();
default void newMethod() {
System.out.println("New Method");
}
}
default method가 등장하게 된 배경
...(중략)... 바로 "하위 호환성"때문이다. 예를 들어 설명하자면, 여러분들이 만약 오픈 소스코드를 만들었다고 가정하자. 그 오픈소스가 엄청 유명해져서 전 세계 사람들이 다 사용하고 있는데, 인터페이스에 새로운 메소드를 만들어야 하는 상황이 발생했다. 자칫 잘못하면 내가 만든 오픈소스를 사용한 사람들은 전부 오류가 발생하고 수정을 해야 하는 일이 발생할 수도 있다. 이럴 때 사용하는 것이 바로 default 메소드다. (자바의 신 2권)
인터페이스의 static 메소드, 자바 8
사실 static메서드는 인스턴스와 관계 없는 독립적인 메서드이기 때문에 인터페이스에 추가하지 못할 이유가 없었다.
그러나 자바를 보다 쉽게 배울 수 있도록 인터페이스의 모든 메서드는 추상 메서드이어야 한다는 단순한 규칙을 위해 static메서드를 허용하지 않았다.
그러나 JDK 1.8부터 인터페이스에 static메서드를 추가할 수 있게 되었다.
interface Myinterface {
void method();
default void newMethod() {
System.out.println("New Method");
}
static void staticMethod() {
System.out.println("Static Method");
}
}
인터페이스의 private 메소드, 자바 9
JDK 1.9 부터 private메서드 역시 추가되었다.
인터페이스에서 private메서드는 default, static메서드에 사용하기 위해 작성되는 메서드이다.
interface Myinterface {
void method();
default void newMethod() {
privateMethod();
System.out.println("New Method");
}
static void staticMethod() {
privateMethod();
System.out.println("Static Method");
}
private void privateMethod() {
System.out.println("Private Method");
}
}
+) 자바 9 이후부터 인터페이스에 default, static, private 메서드 정의가 가능하다. 이제 굳이 추상 클래스를 사용할 필요가 있을까?
->
추상 클래스의 여러가지 기능들을 인터페이스가 가져간 것은 맞다. 그러나 아직 멤버 변수 등 추상 클래스만이 가지고 있는 기능들이 분명히 존재한다. (인터페이스는 상수 선언만 가능하다)
'java > java' 카테고리의 다른 글
[Java] 멀티쓰레드 프로그래밍 (1) | 2021.08.23 |
---|---|
[Java] 예외 처리 (1) | 2021.08.12 |
[Java] 패키지 (2) | 2021.07.21 |
[Java] 상속 (3) | 2021.07.12 |
[Java] 클래스 (1) | 2021.07.07 |