상속(Inheritance)
상속이란?
- 이미 생성한 클래스를 재사용하여 효율적인 개발을 가능하게 하는 기능
- 부모클래스와 자식클래스가 있고, 자식클래스는 부모클래스를 선택하여 그 클래스의 멤버를 (일부) 상속받아 재사용하거나 확장할 수 있다.

상속 규칙
- 부모클래스의 private 접근제어자를 갖는 필드, 메서드는 상속 관계에 포함되지만, 직접 접근할 수는 없어 메서드를 통해 간접적으로 사용할 수 있다.
- 부모클래스와 자식클래스가 서로 다른 패키지에 있다면 부모클래스의 default 접근제어자를 갖는 필드, 메서드를 상속할 수 없다.
- 이 경우에 protected 접근제어자를 사용하면 상속 가능
- 그 외 모두 상속 가능
오버라이딩(over-riding)
- 부모클래스에서 정의한 메서드를 자식클래스에서 재정의(커스텀)하는 것을 메서드 오버라이딩이라고 한다.
- return 타입, 메서드명, 매개변수의 개수, 자료형이 같아야 한다.
- 접근제어자는 부모보다 더 좁은 범위로 만들 수 없다.
상속은 부모클래스와 자식클래스의 관계가 IS-A 일 때 사용하는 것이 적절하다.
HAS-A 관계이거나 서로 관련이 없는 개념의 클래스를 상속하는 것은 혼란을 줄 수 있다.
이제 예제를 통해 상속 개념을 알아보면
예제
//부모클래스
public class Person {
private String name;
// 기본 생성
public Person() {
}
// name 생성자
public Person(String name) {
this.name = name;
}
private String email;
private String phoneNumber;
// getter setter 메서드
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
// 출력을 위한 toString() 메서드
public String toString() {
return name + " # " + email + " # " + phoneNumber;
}
}
먼저 부모클래스엔 이름, 이메일주소, 전화번호 세 가지의 필드와 해당 필드들에 접근하기 위한 getter, setter 메서드가 있다.
가장 아래 toString() 메서드는 객체를 바로 출력하려고 하면 해당 객체의 참조를 출력하게 되는데 그 대신 개발자의 의도대로 출력을 할 수 있도록 하는 메서드이다.
이제 이 Person 클래스를 상속받는 클래스 두 개를 살펴볼 텐데 두 클래스는 각각 학생, 직원인데 둘다 사람에 해당한다.
두 클래스는 모두 부모클래스와 동일한 패키지 내에 위치해 있으며, 위에서 설명한 것처럼 IS-A 관계를 따른다.
//자식클래스 (학생)
public class Student extends Person {
//생성자로 이름과 학교 이름을 생성
//자식클래스의 생성자에서 매개변수로 받은 name을 super(부모)클래스 생성자에 다시 입력하는 구조
//Person 클래스의 생성자를 따라 name 필드에 값이 할당됨
public Student(String name, String collegeName) {
super(name);
this.collegeName = collegeName;
}
//부모클래스와 별개로 자식클래스에서 자유롭게 클래스를 정의할 수 있다.
private String collegeName;
private int year;
public String getCollegeName() {
return collegeName;
}
public void setCollegeName(String collegeName) {
this.collegeName = collegeName;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
}
//자식클래스 (직원)
public class Employee extends Person {
//필드 자체 정의
private String title;
private int salary;
//생성자
public Employee(String name, String title) {
super(name);
this.title = title;
}
public void setTitle(String title) {
this.title = title;
}
public void setSalary(int salary) {
this.salary = salary;
}
//toString() 메서드 오버라이딩
//Person 클래스의 toString() 메서드에 내용을 더함
public String toString() {
return super.toString() + " # " + title + " # " + salary + "원";
}
}
위와 같이 작성한 자식클래스들을 실행할 수 있도록 PersonRunner 클래스를 작성하고 실행해보겠다.
//실행
public class PersonRunner {
public static void main(String[] args) {
//학생 객체 생성
//이메일만 할당
Student sumin = new Student("sumin", "cnu");
sumin.setEmail("XXXX@naver.com");
//사람 객체 생성
//이메일과 전화번호 할당
Person jiyong = new Person("jiyong");
jiyong.setEmail("xxxx@gmail.com");
jiyong.setPhoneNumber("010-xxxx-XXXX");
//사람 객체인 지용 정보 출력
System.out.println(jiyong);
System.out.println();
//학생 객체 수민 정보 출력
System.out.println(sumin);
//직원 객체 생성
//이메일, 전화번호와 더불어 회사명, 급여까지 할당
Employee employee = new Employee("taeu", "programmer");
employee.setEmail("zhdskanf@gmail.com");
employee.setPhoneNumber("010-xxxx-xxxx");
employee.setTitle("Google");
employee.setSalary(9000000);
System.out.println();
//직원 객체 태우 정보 출력
System.out.println(employee);
}
}

우선 자식클래스들을 보면 이미 부모클래스(사람)에서 정의해놓은 필드를 자식클래스에서 별도로 정의하고 있지 않아도
부모가 제공한 생성자와 public 메서드를 통해 간접적으로 상태를 설정할 수 있다는 걸 볼 수 있다.
더 나아가서 각자의 클래스에서 구현하고자 하는 특징에 맞게 필드와 메서드를 추가하거나 부모의 메서드를 오버라이딩 할 수 있다는 것도 알 수 있다.
후기
상속을 한 번 학습한 적이 있지만 시간이 지나면서 내가 기억하는 건 '상속은 부모클래스의 필드와 메서드를 자식클래스가 상속받는다' 정도였는데 이번 학습을 통해 좀 더 디테일한 부분들을 신경 쓰게 되었는데
(IS-A 관계라던지 생성자에서 super() 생성자의 사용, 필드의 간접적 사용, 다형성과의 상관성 등등)
기록을 하며 학습을 하니 더 꼼꼼하게 체크할 수 있는 것 같아서 TIL 작성의 이점을 느끼게 됐다..
'AIBE5 TIL' 카테고리의 다른 글
| [TIL 26/02/11](Java) hashCode(), equals() 오버라이딩 (0) | 2026.02.11 |
|---|---|
| [TIL 26/02/10](Java) 인터페이스 (0) | 2026.02.10 |
| [TIL 26/02/06](Java) 접근제어자와 캡슐화 (0) | 2026.02.06 |
| [TIL 26/02/05](Java) 배열(Array)과 Wrapper Class (0) | 2026.02.05 |
| [TIL 26/02/04] (Java)(2) 데이터타입(기본형, String) (0) | 2026.02.04 |