2010. 7. 7. 00:21

자바(Java)의 `상속`과 다형성(Polymorphism)



하나의 클래스를 만들어 놓고 보면 다음에 다른 클래스를 작성할때 중복되거나 유사한 부분이 심심찮게 발견된다. 이럴때마다 계속 비슷한 코드를 작성하게 되면 효율이 떨어지는 것은 피할 수 없다.

자바에서는 이런 경우에 공통되는 부분들을 공유하면서 구별되는 다른 기능들을 추가할 수 있게 되어 있는데, 이것을 `상속(inheritance)`이라고 한다. 상속을 하는 명령어는 `extends`를 쓴다. 원래의 클래스를 `Book`이라 하고, 상속받는 클래스를 `Note`라고 할때,

class Note extends Book {
    .
    .
    .
}

라고 하면, 상속이 된다. 즉, `super(상위) 클래스`의 모든 것을 그대로 가져왔다는 의미이고 사용도 가능하다. 여기에서도 생성자를 고려해볼 필요가 있는데, 원칙적으로 생성자는 상속되지 않는다. 하지만 `sub(상속받은 하위) 클래스`의 객체가 생성되는 시점에 수퍼 클래스의 기본 생성자가 자동으로 먼저 실행된다. 그럼 신경쓸 필요가 없다고 봐도 되나?

하지만, `자바의 생성자`에서 살펴봤듯이 일단 매개변수가 있는 생성자를 정의하면 기본 생성자는 더 이상 자동으로 생성되지 않는다. 따라서 수퍼 클래스에 매개변수가 있는 생성자가 있게 된다면 기본 생성자도 직접 만들었듯이 서브 클래스에서도 이는 동일하게 적용된다.

그런데, 상속관계에 있는 super와 sub 두 클래스에서 정의하는 생성자가 동일한 형태라고 한다면 똑같은 내용을 반복할 필요없이 super에서 만들어진 생성자를 호출하는 형식으로 할 수 있다. 이때에는 super()를 쓴다.

class Note extends Book {
    Note() {
    }
    Note(String title) {
        super(title) ;
    }
}
이런 경우가 있다. Book 클래스에서도 검색하는 search() 메소드가 있고, 또 Note 클래스에서도 검색하는 search() 메소드가 있을 때 서로 상속관계가 이루어진 상황에서 두 개의 메소드가 서로 충돌을 일으켜 어느 것을 실행해야 할지 모르는 상황이 발생할 수 있을까.

에이~, 자바가 그리 허술할리가... ^^ 전혀 염려할 필요 없다. 이렇게 되면 더 이상 수퍼클래스의 메소드를 사용할 수 없게 되고, 상속받은 서브 클래스의 메소드가 실행된다. 이와 같이 수퍼 클래스에 있는 메소드와 이름에 원형까지 같은 메소드를 서브 클래스에서 새로 정의하는 것을 '오버라이딩(over riding)'이라고 한다.

 `메소드 재정의`라고 할 수 있는 이 개념은 상위 클래스의 내용을 서브 클래스에 맞게 적절히 바꿀 수 있어서, 유연한 프로그래밍이 가능한데, 이처럼 같은 이름의 메소드가 속한 클래스에 따라 그 기능이 달리 수행되는 것을 '다형성(polymorphism)'이라고 한다.