● 인터페이스
인터페이스는 일종의 추상클래스이다. 인터페이스는 추상클래스처럼 추상메서드를 갖지만, 추상글래스와 달리 몸통을 갖춘 일반 메서드 또는 멤버변수를 구성원으로 가질 수 없다. 즉, 추상메서드와 상수만을 멤버로 가질 수 있으며 그외 다른 요소는 허용하지 않는다. 인터페이스는 그 자체적으로 사용되기 보다는 다른 클래스를 작성하는데 도움 줄 목적으로 작성된다. 인터페이스는 키워드로 class 대신 interface를 사용한다. 그리고 접근제어자로 public 또는 default만 사용할 수 있다.
interface 인터페이스이름 {
public static final 타입 상수이름= 값;
public abstract 메서드이름(매개변수목록);
}
인터페이스는 일반적인 클래스와 달리 다음과 같은 제약사항이 있다.
- 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다.
- 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다.
interface PlayingCard {
public static final int SPADE = 4;
final int DIAMOND = 3; // public static final int DIAMOND = 3;
static int HEART = 2; // public static final int HEART = 2;
int CLOVER = 1; // public static final int CLOVER = 1;
public abstarct String getCardNumber();
String getCardKind(); // public abstract String getCardKind();
}
●인터페이스의 상속
인터페이스는 인터페이스로부터만 상속받을 수 있다. 추상메서드는 충돌문제가 발생하지 않으므로 인터페이스는 클래스와 달리 다중상속을 받을 수 있다.
interface Movable {
/** 지정된 위치(x, y)로 이동하는 기능의 메서드 **/
void move(int x, int y);
}
interface Attackable {
/** 지정된 대상(u)을 공격하는 기능의 메서드 **/
void attack(Unit u);
}
interface fightable extends Movable, Attackable { }
클래스의 상속과 마찬가지로 자손 인터페이스(Fightable)는 조상 인터페이스(Moveable, Attackable)에 정의된 멤버를 모두 상속받는다. 그래서 Fightable자체에는 정의된 멤버가 하나도 없지만 조상 인터페이스로부터 상속받은 두 개의 추상메서드, move(int x, int y)와 attack(Unit u)을 멤버로 갖게 된다.
●인터페이스의 구현
인터페이스도 추상클래스처럼 그 자체로는 인스턴스를 생성할 수 없으며, 추상클래스가 상속을 통해 추상메서드를 완성하는 것처럼, 인터페이스도 자신에 정의된 추상메서드의 몸통을 만들어주는 클래스를 작성해야 하는데, 그 방법은 추상클래스가 자신을 상속받는 클래스를 정의하는 것과 다르지 않다. 다만 인터페이스를 구현한다는 의미로 키워드 'implements'를 사용한다.
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). { /* 내용 생략 */ }
}
●인터페이스를 이용한 다형성
다형성을 학습할 때 자손클래스와 마찬가지로 인터페이스 타입의 참조변수로 클래스의 인터스턴스를 참조할 수 있으며, 인스턴스 타입으로의 형변환도 가능하다. 인터페이스 Fightable을 클래스 Fighter가 구현했을 때, Fighter인스턴스를 Fightable타입의 참조변수로 참조하는 것이 가능하다.
Fightable f = (Fightable)new Fighter();
또는
Fightable f = new Fighter();
따라서 인터페이스는 다음과 같이 메서드의 매개변수의 타입으로도 사용 될 수 있다.
void attack(Fightable f) {
//...
}
인터페이스 타입의 매겨변수가 갖는 의미는 메서드 호출 시 해당 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야 한다는 것이다.
class Fighter extends Unit implement Fightable {
public void move(int x, int y) { /* 내용 생략 */ }
public void attack(Fightable f) { /* 내용 생략 */ }
}
위와 같이 Fightable 인터페이스를 구현한 Fighter클래스가 있을 때, attack메서드의 매개변수로 Fighter인스턴스를 넘겨 줄 수 있다. 즉, attack(new Fighter())와 같이 할 수 있다는 것이다. 그리고 아래처럼 메서드의 리턴타입으로 인터페이스를 지정하는 것도 가능하다.
Fightable method() {
...
Fightable f = new Fightable();
return f;
}
리턴타입이 인터페이스라는 것은 메서드가 해당 인스턴스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.
●인터페이스의 장점
마지막으로 인터페이스를 사용하면 어떤 장점이 있는지 짧게 나열해보겠다.
- 개발시간을 단축시킬 수 있다.
- 표준화가 가능하다
- 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.
- 독립적인 프로그래밍이 가능하다.
출처:자바의 정석 기초편(저자: 남궁성, 출판:도우출판)
'java > 객체지향' 카테고리의 다른 글
[JAVA/객체지향] 내부 클래스 (1) | 2023.01.27 |
---|---|
[객체지향] 추상 클래스 (0) | 2021.07.16 |
[객체지향]여러 종류의 객체를 배열로 다루기 (0) | 2021.07.16 |
[객체지향] 다형성(polymorphism) (0) | 2021.07.15 |
[객체지향] 제어자 (0) | 2021.07.14 |