본문 바로가기

IT/자바 Java

[Java 기초] #7. 상속

반응형

상속


상속은 객체지향 프로그래밍의 3대 속성 중 하나 입니다. 상속의 개념을 이용해서, 일반적인 속성을 가지는 클래스와 상세한 속성을 가지는 클래스를 나누어 정의하는 것이 가능해집니다.

상속되는 클래스 (상위 클래스)는 슈퍼클래스, 상속을 받는 클래스 (하위 클래스)는 서브클래스라고 부릅니다.


서브클래스는 extends키워드를 사용해서 정의됩니다.



예제를 보면, 슈퍼클래스에서 정의된 멤버변수나 메서드를 서브클래스에서 그대로 사용하고 있습니다. 즉 서브클래스는 기본적으로 슈퍼클래스에서 정의된 멤버를 그대로 사용할 수 있습니다.

그리고, 자바는 C++ 등의 언어와는 달리 다중 상속을 지원하지 않습니다. 즉 서브클래스는 하나의 슈퍼클래스만 가질 수 있습니다. 물론, 서브클래스가 다른 클래스의 슈퍼클래스가 되는 것은 전혀 문제가 없습니다. (손자 클래스)


상속과 멤버 억세스

private로 정의된 멤버는 동일한 클래스 내의 다른 멤버만 억세스 할 수 있습니다. (#6에서 설명) 이것은 상속을 받는 서브 클래스에서도 마찬가지 입니다. 즉, 슈퍼클래스에서 private로 정의된 멤버 변수는 서브클래스에서 바로 억세스할 수 없습니다.

일반적인 자바 프로그래맹에서는 멤버변수를 private로 정의하고, 외부 클래스 (서브클래스 포함) 에서는 getter/setter 메서드를 이용해 private 변수에 접근합니다.



컨스트럭터와 상속

상속과 관련하여, 자바에서 컨스트럭터는 슈퍼클래스던 서브클래스던 자기 자신이 속한 클래스에서 정의한 멤버의 오브젝트 생성에만 관여합니다.

즉 슈퍼클래스의 컨스트럭터는 슈퍼클래스 부분만, 서브클래스의 컨스트럭터는 서브클래스 부분만 관여합니다.

만일 슈퍼클래스에 컨스트럭터가 정의되어 있지 않다면 슈퍼클래스 부분에는 디폴트 컨스트럭터가 실행됩니다. 하지만 슈퍼클래스에도 컨스트럭터가 정의되어 있다면,  super 키워드를 사용해서 슈퍼클래스의 컨스트럭터를 호출할 수 있습니다.

super 키워드는 super(파라메터_리스트) 와 같이 사용하는데, 서브클래스의 컨스트럭터 내의 첫 라인에 위치해야 합니다.

이렇게 첫 라인에 슈퍼클래스의 컨스트럭터가 오도록 강제함으로써, 자바에서는 슈퍼클래스의 컨스트럭터가 먼저 실행되고 그 다음 서브클래스의 컨스트럭터가 실행된다는 점을 명확하게 하고 있습니다.



super 키워드

자바에서는 슈퍼클래스의 멤버를 억세스하기 위한 방법으로도 super키워드를 사용합니다. 물론 super키워드를 붙인다고 해서 private 멤버를 억세스할 수 있는 것은 아닙니다.

super 키워드는 일반적으로 슈퍼클래스와 서브클래스가 동일한 이름의 변수를 가질 때, 슈퍼클래스의 변수에 접근하기 위한 방법으로 사용됩니다.


슈퍼클래스 레퍼런스 - 서브클래스 오브젝트

자바에서는 타입의 호환성 여부가 항상 체크됩니다. 그리고 타입 간의 하위 호환성을 지원하는데, 이는 클래스간에도 적용 됩니다.

서브클래스는 항상 슈퍼클래스를 포함한 정의를 가지기 때문에, 슈퍼클래스 타입의 레퍼런스는 서브클래스 오브젝트를 가리킬 수 있습니다. 다만 (당연하게도) 서브클래스의 오브젝트 내에서 슈퍼클래스에서 정의된 멤버 부분만 억세스 할 수 있죠.


메서드 오버라이딩

super 키워드에서는 슈퍼/서브클래스간에 동일한 이름의 멤버 변수가 정의된 경우를 설명했는데, 동일한 이름 그리고 동일한 리턴 타입과 파라메터를 가지는 메서드가 양쪽에 정의된 경우 메서드가 오버라이드 되었다고 정의합니다.

오버라이딩 메서드가 정의된 경우 슈퍼클래스에서 정의된 메서드를 실행하려는 경우 super 키워드를 사용하면 됩니다.

오버라이딩은 오버로딩과 헷갈리기 쉽기 때문에 주의가 필요합니다. 리턴 타입이나 시그니쳐가 다른 경우 메서드의 이름이 같다고 해도 오버라이딩이 아니고 오버로딩에 해당됩니다.


메소드 오버라이딩은 자바의 중요한 컨셉 중 하나인 "다아내믹 메서드 디스패칭" 의 근간을 이룹니다. 오버라이딩된 메서드를 컴파일 시점이 아닌 런타임에 해석한다는 의미라고 합니다.



위 예제에서 2차원 도형의 면적을 구하는 메서드인 area() 가 오버라이딩이 왜 필요한지 보여줍니다. 도형의 종류에 따라서 면적을 구하는 공식이 달라지기 때문에, 슈퍼클래스 TwoDShape의 area() 메서드는 실제로 면적을 계산하지 못합니다. 하지만 이를 오버라이딩하는 Triangle 클래스나 Rectangle 클래스에서는 각각의 형식에 맞는 area() 메서드를 오버라이딩하며 정의하고 있습니다.


Abstract classes 추상 클래스

위 예제의 TwoDShape 클래스처럼, 실질적인 메서드 구현은 서브클래스에 맡겨두고 자신은 반드시 구현해야 하는 메서드를 선언만 하는 클래스가 필요한 경우가 많이 있습니다. 자바는 그러한 클래스를 추상 클래스로 선언하도록 하고 있습니다.

위 예제의 area() 메서드처럼 서브클래스에서 실제 구현되어야 하는 메서드는 추상 메서드로 선언되며, 추상 메서드는 추상 클래스 내에서만 존재할 수 있습니다.

추상 클래스의 서브클래스들은 슈퍼클래스에서 정의된 추상메서드를 반드시 구현하여야 합니다. 만일 그렇지 않다면 해당 서브클래스또한 추상클래스로 정의되어야 합니다.


상기한 예제를 추상클래스를 이용해 다시 작성해 보겠습니다.

다른 부분은 모두 동일하고, TwoDShape의 정의 부분과 area() 메서드 부분에 abstract 문구만 넣어 주면 됩니다.



final 파이널

슈퍼클래스에서 메서드를 정의하면서, 서브클래스에서 오버라이딩되는 것을 방지하고 싶을 때 final을 사용합니다. (파이널 메서드)

그리고 클래스 정의 앞에 final 을 선언하면, 해당 클래스의 상속이 불가능해 집니다. (파이널 클래스)

final 키워드의 또 하나의 중요한 사용처는 변수입니다. 변수를 final로 정의하면 해당 변수는 더 이상 변경이 불가능해지므로 "상수"를 정의할 때 final 키워드를 사용합니다.


반응형