인터페이스란 ?
- 인터페이스는 추상클래스처럼 추상메서드를 갖지만 추상클래스보다 추상화 정도가 높아 몸통을 갖춘 일반 메서드 또는 멤버변수를 구성원으로 가질 수 없습니다.
- 인터페이스는 오직 추상메서드와 상수만을 멤버로 가질 수 있습니다.
- 추상클래스와 같이 불완전하므로 그 자체로 사용되기 보다는 다른 클래스를 작성하는 데 도움을 줄 목적으로 사용합니다.
인터페이스의 작성
- 선언 시, 키워드로 interface를 사용합니다.
- 클래스와 같이 접근제어자로 public 또는 default를 사용할 수 있습니다.
- 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다. ( 컴파일러가 자동으로 추가 )
- 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다. ( 컴파일러가 자동으로 추가 )
interface 인터페이스이름 {
public static final 타입 상수이름 = 값;
public abstract 메서드이름 (매개변수목록);
}
인터페이스의 모든 메서드는 추상메서드이어야 하지만, JDK1.8 부터 인터페이스에 static 메서드와 디폴트 메서드 (default method)의 추가를 허용합니다. ( 이 내용은 밑에서 자세히 다룹니다. )
인터페이스의 상속
- 인터페이스는 인터페이스로부터만 상속받을 수 있으며, 클래스와 달리 다중상속이 가능합니다.
interface Movable{
void move(int x, int y) // (x,y)로 이동하는 메서드
}
interface Attackable{
void attack(Unit u); // 지정된 대상( U )을 공격하는 기능의 메서드
}
interface Fightable extends Movable, Attackable{ } // 인터페이스의 다중 상속
- Fightable 인터페이스는 조상 인터페이스 ( Movable, Attackable )에 정의된 멤버를 모두 상속받습니다.
따라서, Fightable 인터페이스는 두 개의 추상메서드 move( int x, int y )와 attack( Unit u )을 멤버로 갖게 됩니다.
인터페이스의 구현
- 인터페이스도 추상클래스처럼 그 자체로는 인스턴스를 생성할 수 없습니다.
- 추상클래스가 상속( extends )을 통해 추상메서드를 완성하는 것처럼, 인터페이스는 클래스의 구현( implements )을 통해 완성됩니다.
- 인터페이스의 메서드 중 일부만 구현한다면, abstract를 붙여서 추상클래스로 선언해야 합니다.
- 상속과 구현을 동시에 할 수 있습니다.
class 클래스이름 implements 인터페이스이름 {
// 인터페이스에 정의된 추상메서드를 구현해야 함.
}
// 인터페이스 구현 예시
class Fighter implements Fightable{
public void move( int x, int y ) { // 추상 메서드 구현 내용 생략 }
public void attack( Unit u ) { // 추상 메서드 구현 내용 생략 }
}
// 인터페이스의 메서드 중 일부만 구현하는 경우 abstract를 사용합니다.
abstract class Fighter implements Fightable{
public void move( int x, int y ) { // 추상 메서드 구현 내용 생략 }
}
// 상속과 구현을 동시에 하는 예시
class Fighter extends Unit implements Fightable{
public void move( int x, int y ) { // 추상 메서드 구현 내용 생략 }
public void attack( Unit u ) { // 추상 메서드 구현 내용 생략 }
}
- 오버라이딩할 때는 조상의 메서드보다 같거나 넓은 범위의 접근 제어자를 지정해야 합니다. ( Movable 인터페이스의 void move( int x, int y )는 public abstract가 생략된 것이기 때문에 구현하는 Fighter 클래스에서는 public 접근 제어자를 사용합니다.
인터페이스를 이용한 다형성
- 자손클래스의 인스턴스를 조상타입의 참조변수로 참조할 수 있는 것처럼, 인터페이스 역시 이를 구현한 클래스의 조상이라 할 수 있으므로 인터페이스의 참조변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있습니다. ( 또한 인터페이스 타입으로의 형변환도 가능합니다. )
Fightable f = (Fightable)new Fighter();
또는
Fightable f = new Fighter();
void attack(Fightable f) { // 인터페이스는 매개변수의 타입으로 사용
...
}
Fightable method(){ // 메서드의 리턴타입으로 인터페이스의 타입을 지정
...
Fighter f = new Fighter();
return f;
}
- 인터페이스는 메서드의 매개변수의 타입으로 사용될 수 있습니다. ( Fightable을 구현한 클래스의 인스턴스를 매개변수로 넘겨 줄 수 있음 )
- 리턴타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 뜻입니다.
인터페이스의 장점
1. 개발시간을 단축시킬 수 있다.
2. 표준화가 가능하다.
3. 서로 관계없는 클래스들에게 관계를 맺어줄 수 있다.
4. 독립적인 프로그래밍이 가능하다.
- 개발시간을 단축시킬 수 있다.
- 인터페이스가 작성되면, 이를 사용해서 프로그램을 작성할 수 있습니다. 메서드를 호출하는 쪽에서는 메서드의 내용과 관계없이 선언부만 알면 되기 때문입니다. 즉, 인터페이스를 구현하는 클래스가 작성될 때까지 기다리지 않고도 인터페이스를 구현하는 쪽과 동시에 개발을 할 수 있습니다.
- 표준화가 가능하다.
- 프로젝트에 사용되는 기본 틀을 인터페이스로 작성하고, 이를 구현하여 프로그램을 작성함으로써 일관되고 정형화된 프로그램의 개발이 가능해집니다.
- 서로 관계없는 클래스들에게 관계를 맺어줄 수 있다.
- 서로 상속관계에 있지도 않고, 같은 조상클래스를 가지고 있지 않은 서로 아무런 관계가 없는 클래스들에게 하나의 인터페이스를 공통적으로 구현하도록 함으로써 관계를 맺어 줄 수 있습니다.
- 독립적인 프로그래밍이 가능하다.
- 인터페이스를 이용하면 클래스의 선언과 구현을 분리시킬 수 있기 때문에 실제 구현에 독립적인 프로그램을 작성할 수 있습니다.
- 클래스와 클래스간의 직접적인 관계를 인터페이스를 이용해서 간접적인 관계로 변경하면, 한 클래스의 변경이 다른 클래스에 영향을 미치지 않는 독립적인 프로그래밍이 가능해집니다.
디폴트 메서드와 static 메서드
- JDK1.8부터 인터페이스에 static 메서드와 디폴트 메서드를 추가할 수 있게 되었습니다.
static 메서드
- static 메서드는 인스턴스와 관계 없는 독자적인 메서드입니다.
- static 메서드의 접근 제어자는 항상 public이며, 생략할 수 있습니다.
디폴트 메서드
- 기존 인터페이스의 메서드를 추가하는 경우는 추상 메서드를 추가하는 것으로 인터페이스를 구현한 모든 클래스에서 새로운 메서드를 구현해야하는 번거로움이 존재했습니다.
- 디폴트 메서드는 이러한 단점을 고려하여, 추상 메서드의 기본적인 구현을 제공하는 메서드입니다.
- 디폴트 메서드는 추상 메서드가 아니기 때문에 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 된다는 장점이 있습니다.
- 키워드 default를 붙이며, 추상 메서드와 달리 일반 메서드처럼 몸통 { }이 있어야 합니다.
- 접근 제어자는 public이고 생략이 가능합니다.
- 새로 추가된 디폴트 메서드가 기존의 메서드와 이름이 중복되어 충돌되는 경우가 발생할 수 있습니다.
( 아래 규칙 참고 )
interface MyInterface{
void method();
default void newMethod(){}; // 디폴트 메서드
}
이름 충돌을 해결하는 규칙
1. 여러 인터페이의 디폴트 메서드 간의 충돌
: 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩해야 한다.
2. 디폴트 메서드와 조상 클래스의 메서드 간의 충돌
: 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.
'Java' 카테고리의 다른 글
[ JAVA의 정석 ] 지네릭스 ( Generics ) (0) | 2023.08.13 |
---|---|
[ Java 의 정석 ] 내부 클래스 ( Inner class ) (0) | 2023.08.03 |
[ Java의 정석 ] 추상클래스 ( abstract class ) (0) | 2023.07.29 |
[ Java의 정석 ] 다형성 ( polymorphism ) (0) | 2023.07.29 |
[ Java의 정석 ] 제어자 ( modifier ) (0) | 2023.07.27 |