9. 상속
상속
Q: 건설회사는 기존 아파트와 조금
다르거나 추가적인 특징들을 가진 새 아파트를 지을 때 어떻게 하는가?
A:
상속
• 상속(inheritance)은 클래스들을 연관시키는 자연스럽고 계층적인 방법이다.
• 상속은 객체 지향 프로그래밍의 가장 중요한 개념 중의 하나이다.
• 상속은 “… 은 …이다” 라는 관계( is-a relationship )를 나타낸다.
• 이 관계를 적용하여 클래스들을 상하
관계로 연결하는 것이 상속이다.
상속
• 상속은 기존 클래스로부터 새로운 클래스를 만드는 것이다.
• 기존 클래스는 부모 클래스 혹은 상위클래스( superclass )라고 부른다.
• 새로 만들어진 클래스는 자식 클래스 혹은 하위클래스 ( subclass )라고 부른다.
• 자식 클래스는 부모 클래스에 정의된
변수들과 메소드들을 상속 받는다.
상속의 목적
• 한 클래스를 처음부터 새로 만들려고 하면 필요한 변수들과 메소드들을 전부 다 새로 만들어야 한다.
• 그러나 상속을 이용하여 기존 클래스로부터 새 클래스를 만들면 일이 훨씬 수월해 진다. 왜냐하면 기존 클래스의 변수들과 메소드들 중 수정할 필요가 있는 것만 재정의하고 새로 필요한 변수들과
메소드들만 정의하면 되기 때문이다.
• 상속의 주목적은 새로운 소프트웨어를 만들기 위해 기존의 소프트웨어를 재사용함으로써 기존
소프트웨어의 설계, 구현 및 시험에 투입된 모든
시간과 노력을 재활용하는 것이다.
하위 클래스 만들기
• 상속 관계를 설정하기 위해서
extends라는 키워드를 사용한다.
// subclass_name라는 클래스의 정의 class subclass_name extends
superclass_name {
// 변수들과 메소드들
}
하위 클래스 만들기
• subclass_name 클래스는
superclass_name 이라는 클래스로부터 변수들과 메소드들을 자동적으로
상속받는다.
• 상속 받은 변수들과 메소드들 중 수정할 필요가 있다면 재정의하여 사용할 수
있다.
• 새로 필요한 변수들과 메소드들이 있다면
새로 정의하여 사용한다.
예: 하위 클래스 만들기
// 예금 계좌를 모델한다 public class Account { double balance; // 잔고
public double getBalance() { return balance;
}
public void deposit( double amount) { balance = balance + amount;
}
public void withdraw(double amount) {
balance = balance - amount;
예: 하위 클래스 만들기
// 저축예금 계좌를 모델한다
public class SavingsAccount extends Account { double interestRate; // 이율
public double getInterestRate() { return interestRate;
}
public void setInterestRate(double rate) { interestRate = rate;
}
}
상속
• 상속 관계는 자주 클래스 그림(class
diagram)으로 보여진다. 화살표가 부모 클래스를 가리킨다.
예금
저축예금
• 위에서 “저축예금은 예금이다”라는 관계가 성립한다. 그러나 반대
방향으로의 관계는 성립하지 않는다.
메소드 재정의(Overriding)
• 하위 클래스는 필요하다면 상속받은 메소드의 정의를 바꿀 수 있다.
• 새 메소드는 상위클래스의 메소드와 같은 머리부를 가져야 하나 메소드 몸체는 달라야 한다.
• 메소드를 호출하는 객체의 유형이 어느
메소드가 호출되었는지를 결정한다.
메소드 재정의
• 부모 메소드는 super 참조를 사용하여 명확하게 호출될 수 있다.
• 한 메소드가 final 메소드로 선언된다면 재정의될 수 없다.
• 재정의의 개념은 변수들에도 적용될 수 있다. 그러나 일반적으로 권장되지
않는다 .
메소드 다중 정의 대 재정의
• 메소드 다중 정의(Overloading)는 같은 클래스 안에 같은 이름을 가지나 다른 머리부를 갖는 여러 메소드들이 있다는 것을 의미한다.
• 메소드 재정의(Overriding)는 같은 머리부를 갖는 두 메소드를 다룬다. 한 메소드는 부모 클래스에 있고 다른 메소드는 자식 클래스에 있다.
• 메소드 다중 정의는 우리가 비슷한 연산을 다른 데이터에 대해 다르게 정의하게 한다.
• 메소드 재정의는 우리가 비슷한 연산을 다른
객체 유형에 대해 다르게 정의하게 한다.
클래스 계층
• 한 클래스의 자식 클래스가 또 다른 클래스의 부모 클래스가 될 수 있다.
• 이와 같이 부모 자식 관계를 확장시켜 계층 구조로 만든 것이 클래스 계층(Class
Hierarchy)이다.
• 같은 부모 클래스의 두 자식 클래스들은 형제들(자매들)이라고 부른다.
• 클래스들의 공통적인 특징들은 클래스 계층의
가능한 위에 놓여져야 한다.
예: 클래스 계층도
교직원
교원 직원
전임 교원 시간 강사 계약 직원
Object 클래스
• Object 클래스는 모든 클래스의 최상위 클래스이다.
• 이 클래스는 java.lang 패키지에 정의되어 있다.
• 모든 클래스는 Object 클래스로부터 상속 받는다.
• Object 클래스는 몇 개의 유용한 메소드들을 가지고 있다.
예:
public boolean equals (Object o) public boolean String toString ()• 한 클래스 내에 toString( ) 메소드를 정의하면 Object
클래스가 제공하는 toString( ) 메소드를 재정의하는 것이다.
• 위의 메소드들이 어떤 객체에서도 호출되도록 한다.
상속과 범위
• 변수나 메소드의 범위(Scope)는 변수나 메소드가 의미를 가지는 코드의 블록이다.
• 상속으로 말미암아 이 범위가 상위 클래스 혹은 그 이상으로 확장될
수 있다.
상속과 범위
변수 :
• 자바는 먼저 변수가 나온 메소드를 조사한다. 지역 변수 혹은 매개 변수인지를 확인한다.
• 다음으로 현 클래스의 변수인지를 확인한다.
• 다음으로 상위클래스의 변수인지를 확인한다.
• 자바는 더 이상 확인할 상위 클래스가 없을 때까지 상속 계층 구조를 올라가면서 확인한다.
메소드 :
• 메소드가 클래스 내에 정의된 메소드인지를 확인한다
.
• 다음으로 상위 클래스에서 정의된 메소드인지를 확인한다.
• 자바는 더 이상 확인할 상위 클래스가 없을 때까지 상속 계층 구조를 올라가면서 확인한다.
범위 명시
자바는 변수나 메소드가 두 가지의 범위 규칙 중 하나를 따르라고 명시할 수 있다:
super 예약어:
상위 클래스의 변수나 메소드를 나타내는 예약어 예: super.setName( )
this 예약어:
현 객체의 메소드나 변수를 나타내는 예약어
예: this.setName( )
예: 상속과 범위
super(xxx) // 상위 클래스의 생성자 메소드를 호출한다 super.xxx // 상위 클래스의 변수를 나타낸다
super.xxx( ) // 상위 클래스의 메소드를 호출한다
this(xxx) // 현 클래스의 생성자 메소드를 호출한다 this.xxx // 현 클래스의 변수를 나타낸다
this.xxx( ) // 현 클래스의 메소드를 호출한다
주 : 다음과 같이 할 수 없다
super.super.<someMethod>
예제 프로그램: 직원
// 직원을 모델한다 class Employee {
public String name;
public double salary;
public Employee (String name, double salary) { this.name = name;
this.salary = salary;
}
public String getName() { return name;
}
public void raiseSalary() { salary *= 1.3;
}
예제 프로그램: 매니저
// 매니저를 모델한다
class Manager extends Employee { public double bonus;
public Manager (String n, double s, double b) { super(n, a);
bonus = b;
}
public void raiseSalary() { // 재정의 salary *= 1.2;
}
}
예제 프로그램: 임원
// 임원을 모델한다
class Executive extends Manager {
public double stock_option; // 스톡 옵션
public Executive (String n, double s, double b, double so) {
super(n, s, b);
stock_option = so;
}
public void raiseSalary() { // 재정의 salary = salary * 1.1;
} }
예제 프로그램: 드라이버 프로그램
// Employee, Manager와 Executive 객체를 만들어 시험한다 class InheritanceTest {
public static void main(String[] args) {
Employee emp = new Employee("홍길동“, 1000.0);
Manager mng = new Manager("강감찬“, 2000.0, 500.0);
Executive exc = new Executive(“이순신”, 4000.0, 1000.0, 100.0);
emp.raiseSalary();
mng.raiseSalary();
exc. raiseSalary();
System.out.println(emp.getName() + " " + emp.salary);
System.out.println(mng.getName() + " " + mng.salary + " " + mng.bonus);
System.out.println(exc.getName() + " " + exc.salary
+ " " + exc.bonus + " " + exc.stock_option);
생성자 메소드와 상속
자바의 규칙 :
• 생성자 메소드의 첫 줄이 상위 클래스의 생성자 메소드를 호출하는 문장이 아니라면 자바는
super( ) 를 첫 줄로 넣는다. 따라서 상위
클래스의 기본 생성자 메소드가 처음에 호출된다.
• 이 규칙의 예외 : this(params) 를 통해 다른 생성자 메소드를 호출한다면 super( ) 에 대한 호출을 연기할 것이다.
• 상위 클래스의 다른 생성자 메소드를 호출하기 위해서 그 메소드를 직접 호출하라
예: super(Name)
가시성 수정자
• 가시성 수정자(Visibility Modifier)는 클래스, 변수, 메소드 앞에 위치하여 그러한 것들이 이용될 수 있는 접근의 범위를 나타낸다.
• public 으로 선언된 변수들과 메소드들은 어디서나 이용할 수 있다.
• private 로 선언된 것들은 정의된 클래스 내에서만 이용할 수 있다.
• protected로 선언된 것들은 자식
클래스들 혹은 자손 클래스들 내에서 이용할
수 있다.
가시성과 접근성
가시성 수정자:
접근 여부: public protected private 모든 클래스 Yes No No
하위 클래스 Yes Yes No 현 클래스의 Yes Yes Yes
객체