학습목표
- 상속 개념 이해
- 상위 클래스와 하위 클래스 개념 이해
- 하위 클래스 만들기
- 상속 계층 구조 이해
- 상속과 범위 이해
- this와 super 사용
- 생성자 메소드 연결 이해
상속의 개념
상속은 새 클래스를 기존 클래스를 확장하여 만드는 프로세스이다. 새로운 클래스를 만들기 위해 사용되는 본래의 클래스는 상위 클래스(superclass) 혹은 부모 클래스(parent class)라고 한다. 새로운 클래스는 하위 클래스(subclass) 혹은 자식 클래스(child class)라고 부른다. 상위 클래스(A)와 하위 클래스(B) 사이에는 ‘B는 A이다’ 라는관계 (IS-A관계)가 성립된다.
실세계의 객체들 사이에는 서로 관계가 있는 경우가 많다. ‘...는 ....이다’라는 rS-A 관계가 대표적이다. 따라서 클래스들 사이에도 IS-A 관계가 적용되는 경우가 많다. 이 관계를 적용하여 클래스들을 상하 관계(혹은 부모/자식 관계)로 연결하는 것이 상속이라고 볼 수 있다.
다음과 같은 경우 학부생 클래스는 학생 클래스의 하위 클래스(혹은 자식 클래스)이고 학생 클래스는 학부생 클래스의 상위 클래스(혹은 부모 클래스)이다.
이렇게 하는 이유는 무엇인가?
클래스를 처음부터 만든다고 하면 필요한 변수들과 메소드들을 전부 다 새로 만들어야 한다. 그러나 기존의 클래스로부터 상속을 통해 클래스를 만드는 경우에는 기존 클래스의 변수들과 메소드들 중 그대로 사용할 펼요가 있는 것들은 상속받아 사용하고 수정할 필요가 있는 것들은 재 정의하여 사용하고 새로 필요한 것들은 새로 정의하여 사용한다. 이렇게 하면 새로운 클래스를 만드는 일이 훨씬 수월해 진다 따라서 새로운 프로그램을 작성하는 경우에 기존의 클래스들을 상속받아 사용하면 프로그래밍의 양이 훨씬 줄어들어 프로그래머의 생산성이 높아진다. 이는 자식이 부모로부터 재산을 상속받으면 세상을 살아 가기가 훨씬 수월해지는 것에 비유할 수 있다. 자바 언어는 설계 단계에서부터 이러한 상속을 이용하기 위해 프로그램 작성시 필요한 클래스들을 미리 만들어 클래스 라이브러리에 포함시켜 놓았다. 이 클래스 라이브라리가 JDK이다. 상속의 주 목적은 새로운 소프트웨어를 만들기 위해 기존의 소프트웨어를 재사용함으로써 기존 소프트웨어의 설계, 구현 및 시험에 투입된 모든 노력을 재활용하는 것이다.
하위 클래스 만들기
새 클래스를 기존의 클래스를 확장하여 만든다는 것을 나타내기 위해 클래스 머리부에 extends라는 예약어를 사용한다. 새 클래스를 기술하는 기본 구문은 다음과 같다.
이 구문은 하위 클래스의 정의를 나타낸다. 하위 클래스는 상위 클래스로부터 변수들과 메소드들을 자동적으로 상속받는다. 그 변수들과 메소드들은 하위 클래스에서 선언된 것처럼 그대로 사용할 수 있다. 물론 그대로 사용하는 것이 적절하지 않고 수정할 필요가 있다면 재정의하여 사용할 수 있다. 하위 클래스에서 새로 필요한 변수들과 메소드들이 있다면 새로 정의하여 사용한다.
학부생을 모델하는 Undergraduate 클래스를 작성하려고 한다. ‘학부생은 학생이다’라는 문장이 맞으므로 우리는 Undergraduate 클래스를 Student 클래스의 하위 클래스로 정의한다. 하위 클래스는 상위 클래스에 추가로 필요한 객체 변수들과 객체 메소드들을 추가하여 정의되는 클래스이다. 학부생의 속성은 이 름 학번과 소속 동아리명이라고 가정한다. 따라서 Undergraduate 클래스에 소속 동아리명을 저장하는 객체 변수가 필요하다. 그 클래스의 메소드들은 객체를 생성하거나 소속 동아리명을 알려주거냐 소속 동아리명을 주어진 값으로 변경한다. 다음 프로그램에 Undergraduate 클래스가 정의된다.
우리는 한 클래스와 다른 클래스 사이에 IS-A 관계가 성립한다면 상속을 사용해야 한다. 만약 두 클래스 사이 에 IS- A 관계가 성립하지 않는다면 상속 대신에 한 클래스의 객체를 다른 클래스 내에 객체 변수로 정 의 하는 것을 고려해야 한다. 그렇다면 이 관계는 HAS-A 관계이다. HAS- A 관계는 한 객체가 다른 객체들로 이 루어져 있을 때 성립한다. 예를 들면, 자동차는 엔진, 차대 (chassis) , 바퀴 같은 여러 개 의 부품들로 이 루어져 있다. 각 부품은 별도의 객체로 여겨질 수 있다. 그러므로 자동차는 부품틀의 집합제이 다. 따라서 자동차를 모델하는 클래스는 각 부품을 나타내는 객제 변수를 가질 수 있다. HAS-A 관계는 집합(aggregation)이라고도 부른다.
매소드 재정의
Undergraduate.java 프로그램에서 Undergraduate 클래스는 매개변수가 없는 toString 메소드를 정의한다. 그러나 Student 클래스도 매 개변수가 없는 같은 이름의 메소드를 가진다. 만약 Undergraduate 클래스가 Student 클래스로부터 toString 메소드를 상속받는다면 Undergraduate 클래스는 toString 매소드를 2개 포함하게 된다. 자바는 이 문제를 피하기 위해 메소드 재정의를 허용한다. 메소드 재정의는 하위 클래스는 필요하다변 상속받은 메소드의 정의를 바꿀 수 있다는 것을 의미한다. 이 경우 새 메소드는 상위 클래스의 메소드와 같은 머리부를 가져야 하나 메소드 폼체는 달라야 한다. 하위 클래스에 재정의된 메소드가 하위 클래스의 모든 객체들에 적응된다. 메소드를 호출하는 객체의 유형이 상위 클래스의 메소드 아니면 하위 클래스의 메소드가 호출되었는지를 결정한다.
그러나 하위 클래스에서 재정의할 수 없게 만들고 싶다면 그 메소드의 머리부의 반환 유형 앞에 final이라는 수정자를 추가하면 된다.
UML 상속 그림
클래스들간의 상속 관계는 UML 클래스 그림 에서 화살표로 표시된다. 하위 클래스에서 상위 클래스로 가는 화살표는 IS-A 관계를 보여준다. 다음 그림은 Student와 Undergraduate 클래스간의 상속 관계를 보여주는 UML 상속 그림이다. under가 Undergraduate 객체를 가리키는 참조 변수라고 가정하자 UML 상속그림 을 통해 다음 메소드 호출에서 getClubName 메소드는 Undergraduate 클래스에서 정의되어 있음을 알 수 있다.
화살표는 특정 메소드가 어느 클래스에서 정의되어 있는지를 찾는데 도움을 준다. 즉 우리가 특정 메소드가 정의되어 있는 클래스를 찾는다면 화살표는 우리가 찾기 위해 따라가야 할 경로를 보여준다. 우리가 Undergraduate 객체에 의해 사용되는 메소드가 정의된 클래스를 찾고 있다면 먼저 Undergraduate 클래스 내에서 찾아본다. 만약 그 클래스에 없다면 상위 클래스인 Student 클래스 내에서 찾아 본다.
클래스 계층
한 클래 스의 자석 클래스가 또 다른 클래 스의 부모 클래 스가 될 수 있다. 또한 한 클래스는 여러 개 의 자식 클래스들을 가질 수 있다. 이와 같이 클래스들간의 부모 자식 관계를 확장시켜 계층 구조로 만든 것이 클래스 계층(class hierarchy) 이다.
클래스 계층에서 상속 절차는 추이적 (transitive)이다. 즉 부모 클래스는 변수들과 메소드들을 자식 클래 스로 넘겨주고 자식 클래스는 상속받은 변수들과 메소드들 뿐만이 아니라 자신의 변수들과 메소드들을 자신의 자식 클래스에 넘겨 준다. 따라서 한 클래스는 클래스 계층에서 자신으로부터 맨 위 클래스 사이의 경로에 있는 모든 클래스로부터 변수들과 메소드들을 상속받을 수 있다.
Object 클래스
Object 클래스는 모든 클래스의 최상위 클래스이다. 이 클래스는 자바의 표준 클래스 라이브러리의 Java.lang 패키지에 정의되어 있다. 모든 클래스들은 Object 클래스로부터 상속받는다. 한 클래스가 기존 클래스의 하위 클래스로 명백하게 정의되지 않는다면 그 클래스는 Object 클래스의 자식 클래스로 여겨진다.
Object 클래스는 몇 개의 유용한 메소드들을 가지고 있다. 이 메소드들은 모든 클래스에 상속된다. 예를 들면, toString 메소드는 Objeo-t 클래스에 정의되어 있다. 따라서 우리가 한 클래스에서 toString 메소드를 정의할 때마다 실제로 Object 클래스의 기존 메소드를 재정의하는 것이다. Object 클래스에 있는 toString 메소드는 클래스의 이름과 다른 정보를 포함하는 문자열을 반환하도록 정의되어 있다. 모든 객체들은 상속을 통해 toString 메소드를 가지고 있다는 것이 보장된다. 따라서 println 메소드는 그것에 넘겨진 어떤 객체에 대한 toString 메소드를 호출할 수 있다.
생성자 메소드 사용
하위 클래스는 자신만의 생성자 메 소드를 가진다. 하위 클래스는 상위 클래 스로부터 생성자 메소드를 상속받지 않는다. 상위 클래스도 자신만의 생성자 메소드를 가진다. 하위 클래스의 생성자 메소드 내에서 첫 번째 문은 상위 클래스의 생성자 메소드를 호출한다.
Undergraduate 클래스 내의 다음 생성자 메소드를 고려하자.
이 생성자 메소드의 첫 번째 문은 상위 클래스의 생성자 메소드를 호출하기 위한 메소드 이름으로 super라는 예약어를 사용한다. Student 클래스 내에 두 개의 생성자 메소드들이 있지만 메소드 호출 super(Name, Number)는 두 개의 매개변수들을 가지는 생성자 메소드에 대한 호출이다. 여기서 생성자 메소드의 이름이 아닌 super를 사용함에 유의하라.
하위 클래스의 생성자 메소드 몸체의 첫 번째 문은 항상 상위 클래스의 생성자 메소드를 호출하는 super를 포함해야 한다. 만약 우리가 한 클래스 내에 정의하는 생성자 메소드의 첫 번째 문이 상위 클래 스의 생성자 메소드를 호출하지 않는다면 자바는 그 생성자 메소드의 첫 번째 문으로 다음 문을 추가한다.
this 사용 호출
우리는 생성자 메소드를 정의할 때 같은 클래스 내의 다른 생성자 메소드를 호출할 수 있다. 이 경우 우리는 this 예약어를 사용한다.
Student 클래스 내의 첫 번째 생성자 메소드를 다음과 같이 this를 사용하여 두 번째 생성자 메소드를 호출하게 할 수 있다.
재정의된 메소드 호출
하위 클래스에서 상위 클래스의 메소드를 재정의한 경우에 그 메소드를 super를 이용하여 호출할 수 있다.
우리는 super 예약어를 이용하여 위 코드와 같이 Student 클래스의 toString 메소드를 호출한다.
상속과 범위
변수나 메소드의 범위는 변수나 메소드가 의미를 가지는 코드의 블록이다. 이 범위는 상속과 밀접하게 연관되어 있다. 지금까지 변수의 범위는 그 변수가 정의되어 있는 메소드 안이나 그 변수를 포함하는 클래스로 한정되었다. 메소드의 범 위도 마찬가지이다. 그러나 상속으로 말미암아 이 범위가 상위 클래스 혹은 그 이 상으로 확장될 수 있다. 프로그램의 한 메소드 내에 한 변수가 나오면 자바는 먼저 그 메소드를 조사하여 그 변수가 지역 변수나 형식 매개 변수인지를 확인한다. 그렇지 않다면 자바는 다음으로 그 메소드를 포함하는 클래스의 변수로 정의되어 있는지를 확인한다. 그렇지 않다면 다음으로 현 클래스의 상위 클래스의 변수가 아닌지 확인한다. 그것도 아니라면 자바는 상속 계층상에 있는 상위 클래스 바로 위에 있는 상위 클래스를 조사한다. 이는 상위 클래스가 없는 클래스에 도달할 때까지 계속된다.
한 클래스에서 한 메소드가 호출되면 자바는 그 메소드가 클래스 내에 정의된 메소드인지 확인한다. 그렇지 않다면 자바는 그 메소드가 상위 클래스에서 정의된 메소드인지를 확인한다. 그렇지 않다면 자바는 상속 계층상에 있는 상위 클래스 바로 위에 있는 상위 클래스를 조사한다. 이는 상위 클래스가 없는 클래스에 도달할 때까지 계속된다.
한 상위 클래스의 생성자 메소드(들)은 하위 클래스에 의해 상속되지 않는다. 이는 우리가 한 클래스에 대한 생성자 메소드를 새로 정의하거나 아니면 컴파일러가 자동적으로 추가하는 기본 생성자 메소드를 사용해야 한다는 것을 의미한다.
따라서 다음의 두 클래스 정의는 서로 같다.
위 클래스에서 컴파일러 에 의해 추가된 생성자 메소드의 문 ‘super();’는 상위 클래스의 생성자 메소드를 호출한다. 만약 한 클래 스의 상위 클래스가 명시되지 않는다면 그것의 상위 클래스는 Object 클래 스이므로 Object 클래스의 기본 생성자 메소드가 호출된다. 우리가 한 클래스의 생성자 메소드를 정의한다면 그 클래스에 기본 생성자 매소드가 추가되지 않는다. 예를 들면 우리가 다음과 같이 클래스를 정의한다고 가정하자.
위 클래스 내의 main 메소드의 다음 문은 대응하는 생성자 메소드가 없기 때문에 맞지 않다.
보여진 프로그램은 뮤지 결의 입장권을 냐타낸다. 각 입장권은 고유한 번호가 있고 정상 가격을 가진다. 입장권은 일반 입장권과 예약 입장권으로 나누어진다. 일반 입장권은 뮤지컬 공연 당일에 구매해야 하고 가격은 신용카드로 결제하면 정상 가격에 5%를 추가하고 현금으로 결제하면 정상가격이다. 예약 입장권은 공연일 30 일 전까지 구매하면 정상 가격의 50%이고 공연일 29 일전 ~ 공연일 10 일 전까지 구매하면 정상 가격의 80%이고 공연일 9일전 ~ 5일전까지 구매하면 정상 가격의 90%이고 공연일 4일전 ~ 1일전까지 구매하면 정상 가격 이다.
다음 프로그램은 뮤지걸의 일반 입장권을 나타낸다. ‘일반 입장권은 입장권이다’라는 문장이 맞으므로 일반 입장권을 나타내는 클래스를 입장권을 나타내는 클래스의 하위 클래스로 한다. this와 super라는 예약어를 사용하는 예를 보여 준다. 또한 일반 입장권은 신용카드로 결제 여부에 따라 가격이 달라지므로 getPrice 메소드를 재정의한다 .
다음 프로그램은 뮤지킬의 예 약 입장권을 나타낸다. ‘예약 입장권은 입장권이다’라는 문장이 맞으므로 예약 입장권을 나타내는 클래 스를 입장권을 나타내는 클래스의 하위 클래스로 한다.
접근 수정자
접근 수정자는 클래스, 변수 메소드 생성자 메소드 앞에 위치하여 그러한 것들이 이용될 수 있는 접근의 범위를 나타낸다. 상속과 관련된 클래스 머리부의 일반적인 기본 구문은 다음과 같다.
[접근수정자] class <하위클래스 이름> extends <상위클래스 이름〉
접근 수정자에는 다음과 같이 4 가지가 있다.
- public: 접근 범위가 공개되어 있어 동일 패키지나 통일 패키지가 아니 더라도 어디서나 접근이 가능하다는 것을 나타낸다.
- protected: 클래스 외부에서는 접근이 불가능하나 하위 클래스에서는 접근이 가능하다는 것을 나타낸다.
- private: 클래스 외부에서는 접근이 불가능하다. 또한 하위 클래스에서도 접근이 불가능하다는 것을 나타낸다.
- package: 이 경우는 클래스 이름 앞에 접근 수정자가 기술되지 않은 경우를 포함한다. 동일 패키지 내의 클래스만이 접근 가능한 클래스를 정의할 때 이용한다.
접근가능성\접근수정자 | public | protected | private | package |
---|---|---|---|---|
모든 클래스 | 접근 가능 | 접근 불가능 | 접근 불가능 | 접근 불가능 |
하위 클래스 | 접근 가능 | 접근 가능 | 접근 불가능 | 접근 불가능 |
클래스 | 접근 가능 | 접근 가능 | 접근 가능 | 접근 가능 |
패키지 | 접근 가능 | 접근 가능 | 접근 불가능 | 접근 가능 |
예제 프로그램 작성
상속의 개념을 이용하여 프로그램을 작성해 보자. 어느 회사 직원들의 봉급을 계산하는 프로그램을 작성 해 보자. 이 회사의 직원 중에는 매니 저가 있고 매 니저 중에는 임원이 있다. 모든 직원은 이름을 가지고 봉급을 받는다. 매니저는 봉급 외에 보너 스를 받을 수 있다. 임원은 봉급과 보너 스 외에 스톡 옵션을 받는다. 직원, 매 니 저와 임원의 초봉은 각각 100,000원, 200, 000원과 400, 000원이다. 매니 저와 임원의 보너 스는 각각 50,000원과 100,000원이다. 임원의 스톡 옵션은 100,000원 상당의 주식이다. 또한 직급에 따라 매년 봉급 인상률이 다르다. 직원, 매니저와 임원의 봉급 인상률은 각각 30%, 20%와 10%이다.
이 문제를 해결하기 위해 필요한 클래스들을 찾아보자. 이 프로그램은 직원, 매니저와 임원을 모델하는 클래스가 필요하다. 또한 전체 프로그램을 제어하는 클래스도 필요하다. 프로그램의 설계 문서는 다음 표에 보여진다.
클래스 | 목적 |
---|---|
Employee | 직원을모덜한다 |
Manager | 매니저를모델한다 |
Exucutíve | 임원을모델한다 |
InherítanceTest | 다른 클래스들을 시험하는 주 클래스이다 |
우리는 직원을 Employee라는 클래스로 매니저를 Manager라는 클래스로 그리고 임원을 Executive라는 클래스로 모델한다. 또한 매니저는 직원이고 임원은 매니저이므로 다음과 같은 상속 계층을 만들 수 있다.
요약
• 상속은 기존 클래스로부터 새로운 클래스를 만드는 것이다. 이 경우 기존 클래스는 상위 클래스이 고 새 클래스는 하위 클래스이다.
• 상속의 목적은 소프트웨어의 재사용이다.
• 상속은 상위 클래스와 하위 클래스 사이에 IS-A 관계를 만든다.
• 하위 클래스는 상위 클래스로부터 변수들과 메 소드들을 자동적으로 상속받는다.
• 하위 클래스는 필요하다면 상속받은 메소드의 정의를 바꿀 수 있다.
• HAS-A 관계는 한 객체가 다른 객체들로 이루어져 있을 때 성립한다.
• UML 상속 그림은 클래스들간의 상속 관계를 보여준다.
• 한 클래스의 하위 클래스가 또 다른 클래스의 상위 클래스가 될 수 있다. 이와 같이 상하 관계를 확장시켜 계층 구조로 만든 것이 클래스 계층이다.
• 클래스 계층에서 공통적인 특정들은 가능한 위에 있는 클래스에서 나타내야 한다.
• Object 클래스는 모든 클래스의 최상위 클래스이다.
• 모든 클래스는 Object 클래스로부터 직접적 혹은 간접적으로 상속받는다.
• 변수와 매소드의 범위가 상속으로 말미암아 상위 클래스 혹은 그 이상으로 확장될 수 있다.
• 예약어 this는 현 객체의 메소드나 변수를 참조하기 위해 사용된다.
• 예약어 super는 상위 클래스의 변수나 메소드를 참조하기 위해 사용된다. 또한 상위 클래스의 생성자 메소드를 super 참조를 사용하여 호출할 수 있다.
• 접근 수정자는 클래스, 변수, 메소드, 생성자 메소드 앞에 위치하여 그러한 것들이 이용될 수 있는 접근의 범위를 나타낸다.
• protected 수정자는 상속을 허락하는 가능한 최선의 캡슐화를 제공한다.
토론이 없습니다