인터페이스는 추상메서드의 집합이다.
인터페이스는 다음과 같은 특징을 가지고 있다.
- 인터페이스의 멤버변수는 public static final 이며, 생략할 수 있다.
- 인터페이스의 메서드는 public abstract 이며, 생략할 수 있다. (단, static 메서드와 디폴트 메서드는 예외)
인터페이스의 상속
- 인터페이스의 조상은 인터페이스만 가능하다.
- 다중 상속이 가능하다.
- 자바에서 클래스의 다중 상속이 안되는 이유는 부모 메서드의 충돌 문제 때문인데, 인터페이스는 메서드의 선언부만 있기때문에 다중 상속시 충돌 문제가 발생하지 않는다.
인터페이스의 구현
인터페이스의 추상 메서드를 완성을 해야 사용이 가능하다.
즉, 인터페이스는 그 자체로 인스턴스를 생성할 수 없고, 인터페이스를 구현한 클래스를 선언 후 사용이 가능하다.
구현한다는 의미의 implements를 사용하여 인터페이스를 구현한다.
interface Fightable{
void move(int x, int y); // public abstract 생략
void attack(Unit u);// public abstract 생략
}
class Fighter implements Fightable{
public void move(int x, int y){/*내용생략*/}
public void attack(Unit u){/*내용생략*/}
}
Fighter 클래스는 Fightable 인터페이스를 구현한 구현 클래스이다.
Fightable 인터페이스의 추상 메서드를 Fighter 클래스에서 모두 오버라이딩하여 작성해야 한다. 모두 오버라이딩하지 않고 일부의 메서드만 작성한다면, Fighter 클래스 앞에 abstract를 붙여 추상 클래스로 선언해야한다.
인터페이스의 다형성
- 인터페이스 타입인 참조 변수에 구현 클래스의 인스턴스를 대입할 수 있다.
Fightable f = new Fighter();
//Fightable f = (Fightable) new Fighter(); 와 같음. 인터페이스 타입으로 자동 형변환.
인터페이스 왜 사용할까? 인터페이스의 장점
1. 변경에 유리한 코드, 느슨한 결합
- 인터페이스는 두 객체 간의 연결을 돕는다. A와 B라는 클래스가 있을 때, 사이에 I라는 인터페이스를 두어 유연한 코드, 변경에 유리한 코드를 만들 수 있다.
[직접적인 관계]
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());
}
}
A의 methodA()에서 매개변수 타입을 B클래스에서 C클래스로 변경하려고 할 때, A클래스의 변경이 불가피하다.
하지만 아래와 같이 인터페이스를 사용하면 A 클래스의 변경이 필요없다.
[간접적인 관계]
class A{
public void methodA(I i){ i.methodTest(); }
}
interface I { void methodTest(); }
class B implements I {
public void methodTest(){
System.out.println("B클래스의 methodTest()");
}
}
class C implements I {
public void methodTest(){
System.out.println("C클래스의 methodTest()");
}
}
class InterfaceTest{
public static main(String args[]){
A a = new A();
a.methodA(new B());//B클래스의 methodTest()
a.methodA(new C());//C클래스의 methodTest()
}
}
2. 개발 시간을 단축시킨다.
A클래스에서 B클래스를 사용한다했을 때, B클래스를 인터페이스의 구현 클래스로 정의한다면 B가 구현이 안되어있어도 A를 작성하는 것이 가능하다. A에서는 선언부만 알면 되기 때문이다.
3. 서로 관계없는 클래스들을 관계 맺어 줄 수 있다.
아무런 관계가 없는 클래스들에게 하나의 인터페이스를 공통적으로 구현하도록 함으로써 관계를 맺어 줄 수 있다.
디폴트 메서드
인터페이스에서 추상 메서드를 추가하거나 변경하면, 그 구현 클래스 변경 역시 불가피하다.
그래서 구현 클래스의 변경을 방지하기 위해 JDK1.8 부터 인터페이스에 디폴트 메서드라는 개념이 추가되었다.
디폴트 메서드는 구현부가 있는 메서드로 인터페이스에 추가되어도 구현 클래스의 변경이 필요없다.
interface MyInterface{
void method();
default void newMethod(){ ... }
}
대신 디폴트 메서드 간의 충돌이 발생할 수 있다.
- 여러 인터페이스의 디폴트 메서드 충돌 시, 인터페이스의 구현 클래스에서 오버라이딩 필요하다.
- 디폴트 메서드와 부모 클래스의 메서드 충돌 시, 부모 클래스의 메서드가 상속된다.
'Java' 카테고리의 다른 글
[Java] 추상화 (feat. 추상 클래스) (0) | 2022.10.15 |
---|---|
[Java] 다형성 (0) | 2022.10.13 |
[Java] 캡슐화 (0) | 2022.10.11 |
[Java] Eclipse 한글 깨짐 해결하기 (0) | 2022.06.09 |
댓글