인터페이스란
- 일종의 추상클래스
- 추상클래스처럼 추상메서드를 갖지만 일반 메서드 또는 멤버변수를 가질 수 없다
- 오직 추상메서드와 상수만을 가질 수 있음
- 그 자체만으로 사용되기 보단 다른 클래스를 작성하는데 도움을 주는 목정으로 작성
인터페이스 작성
키워드로 class 대신 interface를 사용함
또한 interface에서도 클래스와 같이 접근제어자로 public 또는 default를 사용할 수 있다
interface 인터페이스이름 {
public static final 타입 상수이름 = 값;
public abstract 메서드이름(매개변수목록);
}
일반적인 클래스의 멤버들과 달리 인터페이스 멤버에는 다음과 같은 제약사항이 있다
- 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다
- 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다
- 단 static 메서드의 디폴트 메서드는 예외(JDK 1.8부터)
인터페이스의 모든 멤버에 예외없이 적용되기 때문에 생략할 수 있으며,
생략된 제어자는 컴파일러가 자동적으로 추가해준다
인터페이스 상속
인터페이스는 인터페이스로부터만 상속받을 수 있으며
클래스와 달리 다중 상속이 가능하다
클래스의 상속과 마찬가지로 자식 인터페이스는 부모 인터페이스에 정의된 모든 멤버를 상속받는다
인터페이스 구현
인터페이스 그 자체로는 인스턴스를 생성할 수 없으며
자신에 정의된 추상메서드의 몸통을 만들어주는 클래스를 작성해야 한다.
이는 추상클래스의 방법과 동일하며 extends가 아닌 implements를 사용한다
class 클래스이름 implements 인터페이스 이름{
//인터페이스에 정의된 추상메서드를 구현해야 함
}
class Fighter implements Fightable{
public void move(int x, int y) {/*내용 생략*/}
public void attack(Unit u) {/*내용 생략*/}
}
인터페이스를 이용한 다중상속
자바에서 인터페이스로 다중상속을 구현하는 경우는 거의 없다
그 이유는, 두 부모로부터 상속받게 되면 멤버변수의 이름이 같거나 메서드의 선언부는 일치하지만 구현 내용이 다른 경우 어느 한 쪽으로부터의 상속을 포기하던가, 이름이 충돌하지 않도록 부모 클래스를 변경해야하기 때문에 장점도 있지만 단점이 크기 때문이다
하지만 자바도 인터페이스를 통한 다중상속이 가능하다~ 정도로만 알고 넘어가자
인터페이스를 이용한 다형성
다형성은 자식 클래스의 인스턴스를 부모 타입의 참조 변수로 참조하는 것이 가능하다
인터페이스 역시 이를 구현한 클래스의 부모라 할 수 있기 때문에 해당 인터페이스의 참조변수로
이를 구현한 클래스의 인스턴스를 참조할 수 있으며
인터페이스 타입으로의 형변환 역시 가능하다
따라서 다음과 같이 매개변수의 타입으로 사용될 수 있다
인터페이스의 장점
개발시간을 단축시킬 수 있다
인터페이스가 작성되면, 이를 사용해서 프로그램을 작성하는 것이 가능하다
메서드를 호출하는 쪽에서는 메서드의 내용에 관계없이 선언부만 알면 되기 때문
그리고 동시에 다른 한 쪽에서는 인터페이스를 구현하는 클래스를 작성하게 하면,
인터페이스를 구현하는 클래스가 작성될 때 까지 기다리지 않고 양쪽에서 동시에 개발을 진행할 수 있다
표준화가 가능하다
프로젝트에 사용되는 기본 틀을 인터페이스로 작성한 다음,
개발자들에게 인터페이스를 구현하여 프로그램을 작성하도록 함으로써
보다 일관되고 정형화된 프로그램의 개발이 가능하다
서로 관계없는 클래스들에게 관계를 맺어줄 수 있다
서로 상속관계에 있지도 않고, 같은 조상클래스를 가지고 있지 않은 아무 관계 없는 클래스들에게
하나의 인터페이스를 공통적으로 구현하도록 함으로써 관계를 맺어 줄 수 있다
독립적인 프로그래밍이 가능하다
인터페이스를 이용해 클래스의 선언과 구현을 분리시킬 수 있기 때문에
실제 구현에 독립적인 프로그램을 작성하는 것이 가능하다
클래스와 클래스 간의 직접적인 관계를 인터페이스를 이용해 간접적인 관계로 변경하면,
한 클래스의 변경이 관련된 다른 클래스에 영향을 미치지 않는 독립적인 프로그래밍이 가능하다
인터페이스의 이해
인터페이스를 이해하기 위해서는 다음 두 가지 사항을 반드시 염두해 둬야 한다
- 클래스를 사용하는 쪽(User)과 제공하는 쪽(Provider)이 있다
- 메서드를 호출하는 쪽(User)에서는 사용하려는 메서드(Provider)의 선언부만 알면 된다(내용은 몰라도 됨)
class A {
public void methodA(B b){
b.methodB();
}
}
class B{
public void methodB(){
System.out.println("methodB()");
}
}
class InterfaceTest{
public static void main(String args[]){
A a= new A();
a.methodA(new B());
}
}
다음과 같이 classA와 classB가 있다고 할 때,
classA는 classB의 인스턴스를 생성하고 메서드를 호출한다
이 두 클래스는 서로 직접적인 관계에 있으며 이것을 간단히 'A-B'라고 표현해보면
이 경우 class A를 작성하기 위해서는 class B가 이미 작성되어 있어야 한다
그리고 class B의 methodB()의 선언부가 변경되면, 이를 사용하는 class A 또한 변경되어야 한다
이렇게 한쪽이 변경되면 다른 쪽이 변경되어야 한다는 단점이 있다
그러나 A가 B를 직접 호출하지 않고 인터페이스를 매개체로 해서 A가 인터페이스를 통해 B에 접근하도록 하면
B에 변경사항이 생기거나 B가 다른 클래스로 대체된다해도 A에는 전혀 영향을 받지 않도록 하는 것이 가능하다
두 클래스 간의 관계를 간접적으로 변경하기 위해서는 먼저 인터페이스를 이용해 classB의 선언과 구현을 분리해야한다
1. class B에 정의된 메서드를 추상메서드로 정의하는 인터페이스를 정의한다
interface I {
public abstract void methodB();
}
2. class B가 인터페이스 I를 구현하도록 한다
class B implements I {
public void methodB() {
System.out.println("methodB in B class");
}
}
이제 class A는 class B대신 인터페이스 I를 사용해 작성할 수 있다
class A {
public void methodA(I i) {
i.methodB();
}
}
클래스 A와 클래스 B는 'A-B' 에서 'A - I - B'의 간접적인 관계로 바뀐것을 볼 수 있다
클래스 A는 인터페이스를 통해 실제로 사용하는 클래스의 이름을 몰라도 되고
심지어는 실제로 구현된 클래스가 존재하지 않아도 문제되지 않는다
클래스 A는 오직 직접적인 관계에 있는 인터페이스 I의 영향만을 받는다
디폴트 메서드와 static 메서드
JDK 1.8 부터 디폴트 메서드와 static 메서드도 인터페이스에 추가 할 수 있다
디폴트 메서드
인터페이스의 경우 부모 클래스에 새로운 메서드를 추가하는 것은 까다로운 과정이 필요하다
인터페이스에 새로운 메서드가 추가되면 이 인터페이스를 구현한 기존의 모든 클래스들이 새로 추가된 메서드를 구현해야 하기 때문이다
아무리 설계를 잘해도 언젠가 변경은 발생하기 때문에 디폴트 메서드(default method)가 고안되었다
디폴트 메서든느 추상 메서드의 기본적인 구현을 제공하는 메서드로,
추상 메서드가 아니기 대문에 디폴트 메서드가 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 된다
interface MyInterface {
void method();
default void newMethod() {}
}
이렇게 디폴트 메서드를 추가하면 기존의 MyInterface를 구현한 클래스를 변경하지 않아도 된다
대신 새로 추가된 디폴트 메서드가 기존의 메서드와 이름이 중복되어 충돌하는 경우가 발생하는데
충돌을 해결하는 규칙은 다음과 같다
- 여러 인터페이스의 디폴트 메서드 간의 충돌
인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩 해야 함
- 디폴트 메서드와 부모 클래스의 메서드 간의 충돌
부모 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다
'Language > Java' 카테고리의 다른 글
[Java] 내부 클래스(Inner Class) (0) | 2024.04.18 |
---|---|
[Java] 객체지향 프로그래밍 - 다형성과 추상클래스 (0) | 2024.04.08 |
[Java] 객체지향 프로그래밍 - 제어자 (0) | 2024.04.05 |
[Java] 객체지향 프로그래밍 - package와 import (0) | 2024.04.05 |
[Java] 객체지향 프로그래밍 - 오버라이딩(overriding) (0) | 2024.04.05 |