인터페이스란?

서로 다른 클래스의 공통적인 요소를 뽑아서 만든 클래스.

-일종의 추상클래스지만 추상클래스보다 추상화 정도가 높아서 추상클래스와는 달리 일반 메서드또는 멤버변슈를 구성원으로 가질 수 없다. 오직 추상메서드와 상수만으로만 이룰 수 있다.

인터페이스는 상속이 아닌 구현한다고 표현한다.

 

 

인터페이스의 특징.

-추상클래스보다 추상화 정도가 높아서 달리 몸통을 갖춘 일반 메서드 또는 멤버변수를 구성원으로 가질 수 없다. (오직 추상메서드와 상수만을 멤버로 가질 수 있다. )

-모든 멤버변수는 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 )

아래와 같이 인터페이스를 통해 다중상속을 구현할 수 있다.

  1. public class Tv {   
  2.       protected boolean power;   
  3.       protected int channel;   
  4.       protected int volume;   
  5.       public void power() { power = ! power;}   
  6.       public void channelUp() { channel++;}   
  7.       public void channelDown() { channel--;}   
  8.       public void volumeUp() { volume++;}   
  9.       public void volumeDown() { volume--;}   
  10. }   
  11.   
  12. public class VCR {   
  13.       protected int counter;             // VCR의 카운터   
  14.       public void play() {   
  15.             // Tape을 재생한다.   
  16.       }   
  17.       public void stop() {   
  18.             // 재생을 멈춘다.   
  19.       }   
  20.      public void reset() {               
  21.            counter =0;   
  22.      }   
  23.      public int getCounter() {   
  24.            return counter;   
  25.      }   
  26.      public void      setCounter(int c) {   
  27.            counter = c;   
  28.      }   
  29. }   
  30.   
  31. public interface IVCR {   
  32.       public void play();   
  33.       public void stop();   
  34.       public void reset();   
  35.      public int getCounter();   
  36.      public void setCounter(int c);   
  37. }   
  38.   
  39. public class TVCR extends Tv implements IVCR {   
  40.       VCR vcr = new VCR();         
  41.       public void play() {   
  42.             vcr.play();   // 코드를 작성하는 대신 VCR인스턴스의 메서드를 호출하면 된다.   
  43.       }   
  44.       public void stop() {   
  45.             vcr.stop();   
  46.       }   
  47.       public void reset() {   
  48.            vcr.reset();   
  49.      }   
  50.      public int getCounter() {   
  51.           return vcr.getCounter();   
  52.      }   
  53.      public void setCounter(int c) {   
  54.           vcr.setCounter(c);   
  55.      }   
  56. }   
자바에서는 다중상속이 안되지만 이처럼 인터페이스를 사용하면 다중상속의 효과를 얻을 수 있다. 또한 이렇게 하면 VCR클래스의 내용이 변경되어도 변경된 내용이 TVCR클래스에도 자동적으로 반영되는 효과도 얻을 수 있다. 그리고 인터페이스를 사용하면 다형적 특성을 이용할 수 있다는 장점이 있다.

인터페이스를 통해 다형성을 구현할 수도 있다.
  1. class ParserTest {   
  2.       public static void main(String args[]) {   
  3.             Parseable parser = ParserManager.getParser("XML");   
  4.             parser.parse("document.xml");   
  5.             parser = ParserManager.getParser("HTML");   
  6.             parser.parse("document2.html");   
  7.       }   
  8. }   
  9.   
  10. interface Parseable {   
  11.       public abstract void parse(String fileName);       // 구문 분석작업을 수행한다.   
  12. }   
  13.   
  14. class ParserManager {   
  15.      // 리턴타입이 Parseable인터페이스이다.   
  16.       public static Parseable getParser(String type) {         
  17.             if(type.equals("XML")) {   
  18.                return new XMLParser();   
  19.             } else {   
  20.                Parseable p = new HTMLParser();   
  21.                return p;   
  22.                // return new HTMLParser();       위의 두 줄을 간단히 할 수 있다.   
  23.             }   
  24.       }   
  25. }   
  26.   
  27. class XMLParser implements Parseable {   
  28.       public void parse(String fileName) {   
  29.           /* 구문 분석작업을 수행하는 코드를 적는다. */   
  30.             System.out.println(fileName + " - XML parsing completed.");   
  31.       }   
  32. }   
  33.   
  34. class HTMLParser implements Parseable {   
  35.       public void parse(String fileName) {   
  36.           /* 구문 분석작업을 수행하는 코드를 적는다. */   
  37.             System.out.println(fileName + " - HTML parsing completed.");   
  38.       }   
  39. }   

실행결과
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 클래스를 변경하지 않아도 된다.


아래는 또다른 예이다.
  1. class RepairableTest   
  2. {   
  3.       public static void main(String[] args)   
  4.       {   
  5.             Tank t = new Tank();   
  6.             DropShip d = new DropShip();   
  7.   
  8.             Marine m = new Marine();   
  9.             SCV       s = new SCV();   
  10.   
  11.             s.repair(t);       // SCV가 Tank를 수리하도록 한다.   
  12.             s.repair(d);   
  13. //             s.repair(m);       에러발생 : repair(Repairable) in SCV cannot be applied to (Marine)   
  14.       }   
  15. }   
  16.   
  17. interface Repairable {}   
  18. class GroundUnit extends Unit {   
  19.       GroundUnit(int hp) {   
  20.             super(hp);   
  21.       }   
  22. }   
  23.   
  24. class AirUnit extends Unit {   
  25.       AirUnit(int hp) {   
  26.             super(hp);   
  27.       }   
  28. }   
  29.   
  30. class Unit {   
  31.       int hitPoint;   
  32.       final int MAX_HP;   
  33.       Unit(int hp) {   
  34.             MAX_HP = hp;   
  35.       }   
  36.       //...   
  37. }   
  38.   
  39. class Tank extends GroundUnit implements Repairable {   
  40.       Tank() {   
  41.             super(150);             // Tank의 HP는 150이다.   
  42.             hitPoint = MAX_HP;   
  43.       }   
  44.   
  45.       public String toString() {   
  46.             return "Tank";   
  47.       }   
  48.       //...   
  49. }   
  50.   
  51. class DropShip extends AirUnit implements Repairable {   
  52.       DropShip() {   
  53.             super(125);             // Dropship의 HP는 125이다.   
  54.             hitPoint = MAX_HP;   
  55.       }   
  56.   
  57.       public String toString() {   
  58.             return "DropShip";   
  59.       }   
  60.       //...   
  61. }   
  62.   
  63. class Marine extends GroundUnit {   
  64.       Marine() {   
  65.             super(40);   
  66.             hitPoint = MAX_HP;   
  67.       }   
  68.       //...   
  69. }   
  70.   
  71.   
  72. class SCV extends GroundUnit implements Repairable{   
  73.       SCV() {   
  74.             super(60);   
  75.             hitPoint = MAX_HP;   
  76.       }   
  77.   
  78.       void repair(Repairable r) {   
  79.             if (r instanceof Unit) {   
  80.                   Unit u = (Unit)r;   
  81.                   while(u.hitPoint!=u.MAX_HP) {   
  82.                         /* Unit의 HP를 증가시킨다. */   
  83.                         u.hitPoint++;   
  84.                   }   
  85.                   System.out.println( u.toString() + "의 수리가 끝났습니다.");   
  86.             }   
  87.       }         
  88.       //...   
  89. }   
repair메서드의 매개변수 r은 Repairable타입이기 때문에 인터페이스 Repairable에 정의된 멤버만 사용할 수 있다.
그러나 Repairable에는 정의된 멤버가 없으므로 이 타입의 참조변수로는 할 수 있는 일은 아무 것도 없다.
그래서 instanceof연산자로 타입을 체크한 뒤 캐스팅하여 Unit클래스에 정의된 hitPoint와 MAX_HP를 사용할 수 있도록 하였다.
그 다음엔 유닛의 현재체력(hitPoint)이 유닛이 가질 수 있는 최고체력(MAX_HP)이 될 때까지 체력을 증가시키는 작업을 수행한다.

 Marine은 Repairable인터페이스를 구현하지 않았으므로 SCV클래스의 repair메서드의 매개변수로 Marine을 사용하면 컴파일 시에 에러가 발생한다.

Posted by 윤연식
,