인터페이스란?
서로 다른 클래스의 공통적인 요소를 뽑아서 만든 클래스.
-일종의 추상클래스지만 추상클래스보다 추상화 정도가 높아서 추상클래스와는 달리 일반 메서드또는 멤버변슈를 구성원으로 가질 수 없다. 오직 추상메서드와 상수만으로만 이룰 수 있다.
인터페이스는 상속이 아닌 ‘구현’한다고 표현한다.
인터페이스의 특징.
-추상클래스보다 추상화 정도가 높아서 달리 몸통을 갖춘 일반 메서드 또는 멤버변수를 구성원으로 가질 수 없다. (오직 추상메서드와 상수만을 멤버로 가질 수 있다. )
-모든 멤버변수는 public static final이어야 하며 생략가능하다.( 자동으로 인식 )
-모든 메서드는 public abstract이어야 하며 생략가능하다.( 자동으로 인식 )
-인터페이스로부터만 상속받을 수 있다.
-다중상속이 가능하다.
-추상클래스는 모든 접근제한자를 사용가능하지만 인터페이스는 public만 가능하다.
인터페이스는 어떤 경우에 사용하는가?
-추상클래스와 마찬가지로 완성되지 않은 상태이므로 그 자체만으로 사용되기 보다는 다른 클래스를 작성하는데 도움을 주는 목적으로 사용한다.
-서로 다른 클래스들의 공통요소를 뽑아 표준화를 시키고 관리를 용이하게 만든다.
-다중상속을 하고자 하는 경우.
다시 말해 인터페이스는 다형성을 사용하기 위한 것이다.
인터페이스를 사용함으로써 생기는 장점?
-개발시간을 단축시킬 수 있다.
-표준화가 가능하다.
-서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.
-독립적인 프로그래밍이 가능하다.
인터페이스는 어떻게 사용하는가?
-보통 클래스를 작성하는 것과 같지만 class 대신 interface를 사용한다.
-구현할 때는 extends 대신 implements를 사용한다.
예)
interface Fightable { }; ( 인터페이스는 메서드명을 ~able이라고 주로 쓴다. )
interface Fightable extends Movable, Attackable { };
class KingOfFighter extends People implements Fightable, Flyable, Magic { };
아래는 사용 예제이다. (자바의정석 참조. http://cafe.naver.com/javachobostudy/44 )
아래와 같이 인터페이스를 통해 다중상속을 구현할 수 있다.
인터페이스를 통해 다형성을 구현할 수도 있다.
실행결과
document.xml - XML parsing completed.
document2.html - HTML parsing completed.
위의 예제에서 보시다시피 인터페이스를 사용하면,
Parseable p = new HTMLParser();
return p;
위와 같은 구문을 return new HTMLParser(); 와 같이 간단히 한줄로 할 수 있으며,
Parseable parser = ParserManager.getParser("XML");
와 같이 Parseable 인터페이스를 사용하기 때문에 다른 클래스가 추가되거나 변경되어도
ParserTest 클래스를 변경하지 않아도 된다.
아래는 또다른 예이다.
- class RepairableTest
- {
- public static void main(String[] args)
- {
- Tank t = new Tank();
- DropShip d = new DropShip();
- Marine m = new Marine();
- SCV s = new SCV();
- s.repair(t); // SCV가 Tank를 수리하도록 한다.
- s.repair(d);
- // s.repair(m); 에러발생 : repair(Repairable) in SCV cannot be applied to (Marine)
- }
- }
- interface Repairable {}
- class GroundUnit extends Unit {
- GroundUnit(int hp) {
- super(hp);
- }
- }
- class AirUnit extends Unit {
- AirUnit(int hp) {
- super(hp);
- }
- }
- class Unit {
- int hitPoint;
- final int MAX_HP;
- Unit(int hp) {
- MAX_HP = hp;
- }
- //...
- }
- class Tank extends GroundUnit implements Repairable {
- Tank() {
- super(150); // Tank의 HP는 150이다.
- hitPoint = MAX_HP;
- }
- public String toString() {
- return "Tank";
- }
- //...
- }
- class DropShip extends AirUnit implements Repairable {
- DropShip() {
- super(125); // Dropship의 HP는 125이다.
- hitPoint = MAX_HP;
- }
- public String toString() {
- return "DropShip";
- }
- //...
- }
- class Marine extends GroundUnit {
- Marine() {
- super(40);
- hitPoint = MAX_HP;
- }
- //...
- }
- class SCV extends GroundUnit implements Repairable{
- SCV() {
- super(60);
- hitPoint = MAX_HP;
- }
- void repair(Repairable r) {
- if (r instanceof Unit) {
- Unit u = (Unit)r;
- while(u.hitPoint!=u.MAX_HP) {
- /* Unit의 HP를 증가시킨다. */
- u.hitPoint++;
- }
- System.out.println( u.toString() + "의 수리가 끝났습니다.");
- }
- }
- //...
- }
그러나 Repairable에는 정의된 멤버가 없으므로 이 타입의 참조변수로는 할 수 있는 일은 아무 것도 없다.
그래서 instanceof연산자로 타입을 체크한 뒤 캐스팅하여 Unit클래스에 정의된 hitPoint와 MAX_HP를 사용할 수 있도록 하였다.
그 다음엔 유닛의 현재체력(hitPoint)이 유닛이 가질 수 있는 최고체력(MAX_HP)이 될 때까지 체력을 증가시키는 작업을 수행한다.
Marine은 Repairable인터페이스를 구현하지 않았으므로 SCV클래스의 repair메서드의 매개변수로 Marine을 사용하면 컴파일 시에 에러가 발생한다.