2010. 7. 7. 16:19

자바(Java) 추상 클래스(Abstract Class)와 인터페이스(Interface)



오버라이딩으로 인한 '다형성(ploymorphism)'은 '추상 클래스'나 '인터페이스' 개념에서 더욱 확장성을 가진다.

추상 클래스(abstract class)는 하나 이상의 '추상 메소드'를 가지는 클래스인데, 추상 메소드라는 것은 몸체 알맹이가 없이 메소드 원형만 있는 껍데기 메소드를 말한다.

그리고 인터페이스(interface)는 모든 메소드가 추상 메소드로만 이루어져 있는 특수 클래스이다. 이 추상클래스와 인터페이스는 내용이 없는 메소드를 가지고 있으므로 자체로는 객체를 생성할 수 없다. 그러면 어떻게 사용하는가?

상속을 거쳐 오버라이딩이라는 과정을 거쳐야 인스턴스를 생성해서 객체로 사용이 가능하다. 그런데, 추상 클래스를 상속받을 때에는 extends 키워드를 그대로 쓰지만, 인터페이스를 상속받을 때에는 'implements'라는 키워드를 사용해야 한다. 만약 인터페이스가 인터페이스를 상속 받는다면 이때는 extends를 사용한다. extends는 하나의 클래스를 상속할 수 있지만 implements는 여러개의 인터페이스 상속이 가능하다.

예를 들자면, 우선 인터페이스는

  1: interface DataStructure {
  2:     int strength ;
  3:     String name ;
  4:     String occupation ;
  5:     .
  6:     .
  7:     void setName() ;
  8:     int getStrength() ;
  9:     .
 10:     .     
 11: }
이렇게 메소드들의 원형만 적어주는 것으로 정의된다. 변수들 앞에는 public static final이 메소드들 앞에는 public abstract가 모두 생략되어 있지만 묵시적으로 선언되어 있다. 한편, 추상 클래스는
  1: abstract class WeaponSystem {
  2:     protected weaponPower ;
  3: 
  4:     public double getWeaponPower() {
  5:         return weaponPower ;
  6:     }
  7: 
  8:     abstract public void weaponPower() ;
  9: }
추상 클래스에서 메소드는 구현되어 있어도 되고 그렇지 않아도 상관없다. 다만 추상 메소드만큼은 블록이나 내용없이 선언만 되어 있어야 한다. 이렇게 만들었으면 활용을 해야 된다. 코드 설명을 하자면 무기체계라는 추상 클래스를 만들고 시지탱크 클래스가 그것을 상속받아서 무기의 화력을 정하는 메소드에 기본을 150으로 설정하도록 오버라이딩을 했다.
  1: class SiegeTank extends WeaponSystem {
  2:     .
  3:     .
  4:     public void weaponPower() {
  5:         weaponPower = 150 ;
  6:     }
  7:     .
  8:     .
  9: }
인터페이스 역시 이와 같은 방법으로 사용하지만 위에서 언급했듯이 상속을 받으려면 implements로 써줘야 한다.
  1: class SiegeTank implements WeaponSystem {
  2:     .
  3:     .
  4:     .
  5: }
이렇게 추상 클래스와 인터페이스를 사용하는 이유는 하나의 틀을 만들어 놓고, 거기에 맞춰 일관성 있는 프로그래밍을 하기 위함인데 프로젝트의 규모가 커질수록 소프트웨어 제작에 참여하는 사람들이 많을수록 이러한 점이 더욱 요구된다.