[TIL 26/02/09](Java) 상속
2026. 2. 9. 22:41
상속(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 작성의 이점을 느끼게 됐다..