
상속은 객체 지향 프로그래밍(OOP)의 핵심 개념 중 하나로, 기존 클래스(부모/슈퍼 클래스)의 field와 method를 재사용해서 새로운 클래스(자식/서브 클래스)를 만드는 방식이다. 즉, “공통 기능은 위에 모으고”, “개별 기능은 아래에서 확장”하는 구조로 코드를 설계한다.
상속을 쓰면 여러 클래스에 반복되는 코드를 부모 클래스에 모아두고, 자식 클래스들이 재사용할 수 있다.
예를 들어 Animal(동물)에 공통 속성(이름, 나이)과 공통 행동(move)을 정의해두면, Dog/Cat/Human/Tiger 같은 자식 클래스는 자신만의 고유 기능만 추가하면 된다.
결과적으로 코드 중복을 줄이고 유지보수도 쉬워진다.
1) 단일 상속: Java는 한 번에 하나의 부모 클래스만 상속 가능하다.
2) super: 부모의 생성자/field/method 접근에 사용한다.
3) method override: 자식이 부모의 기능을 “재정의”할 수 있다.
4) final class: 클래스에 final이 붙으면 상속 불가.
5) final method: 메서드에 final이 붙으면 override 불가.
상속은 “IS-A 관계”를 표현한다. 예: Tiger is an Animal, Human is an Animal 부모는 더 일반적이고 넓은 범위, 자식은 더 구체적이고 특징이 있는 존재로 설계한다.
super() : 부모 클래스의 생성자를 호출
super.method() : 부모 클래스의 메서드를 호출
아래 코드는 Animal(부모)을 기준으로 Human/Tiger(자식)가 상속받아 확장하는 구조를 보여준다.
import java.util.Arrays;
/*
Backend/OOP logic in Java: Inheritance + Override + super usage
*/
class Animal {
private String animalName;
private int animalAge;
public Animal() {}
public Animal(String animalName) {
this.animalName = animalName;
}
public Animal(int animalAge) {
this.animalAge = animalAge;
}
public Animal(String animalName, int animalAge) {
this.animalName = animalName;
this.animalAge = animalAge;
}
public String getAnimalName() {
return animalName;
}
public void setAnimalName(String animalName) {
this.animalName = animalName;
}
public int getAnimalAge() {
return animalAge;
}
public void setAnimalAge(int animalAge) {
this.animalAge = animalAge;
}
public void move() {
System.out.println("움직입니다.");
}
}
class Human extends Animal {
public Human() {
System.out.println("사람 객체가 생성되었습니다.");
}
@Override
public void move() {
System.out.println("사람이 두 발로 걷습니다.");
}
public void read(String book) {
System.out.println(getAnimalName() + "이 " + book + "를 읽는 중입니다.");
}
}
class Tiger extends Animal {
private double weight;
public Tiger() {}
public Tiger(String animalName, int animalAge, double weight) {
super(animalName, animalAge); // super() to call parent constructor
this.weight = weight;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public void hunt() {
System.out.println(getAnimalName() + "(이)가 사냥을 합니다.");
}
public void hunt(String prey) { // overload
System.out.println(getAnimalName() + "(이)가 " + prey + "을(를) 사냥합니다.");
}
@Override
public void move() {
System.out.print("호랑이가 ");
super.move(); // call parent method
}
}
public class Main {
public static void main(String[] args) {
Animal animal1 = new Animal();
animal1.move();
animal1.setAnimalName("동물");
animal1.setAnimalAge(12);
Tiger tiger1 = new Tiger();
tiger1.setAnimalName("호랑이");
tiger1.setAnimalAge(1);
System.out.println("이 호랑이의 이름은 " + tiger1.getAnimalName()
+ "이고, 나이는 " + tiger1.getAnimalAge() + "살 입니다.");
tiger1.move();
tiger1.hunt();
tiger1.hunt("사료");
tiger1.setWeight(1.4);
System.out.println(tiger1.getAnimalName() + "의 몸무게는 " + tiger1.getWeight() + "t 입니다.");
System.out.println("------------------------------------------------");
Human human1 = new Human();
human1.move();
human1.setAnimalName("여러분이름");
human1.setAnimalAge(35);
System.out.println("안녕하세요, 제 이름은 " + human1.getAnimalName()
+ "이고 나이는 " + human1.getAnimalAge() + "살입니다."
+ "\n내년에는 " + (human1.getAnimalAge() + 1) + "살이 됩니다.");
human1.read("자바의 기초");
}
}
- 부모 클래스는 자식 클래스의 고유 메서드를 호출할 수 없다. (예: Animal 타입 변수로 hunt() 호출 불가)
- override는 “부모가 가진 메서드”를 “자식이 같은 시그니처로 재정의”하는 것이다.
- super.move()처럼 부모 동작을 일부 재사용하면서 자식 동작을 덧붙이는 패턴이 자주 나온다.
- final은 상속/오버라이딩을 막아 설계를 고정할 때 사용한다.
상속은 공통 코드를 부모에 모으고, 자식이 이를 재사용/확장하는 구조다. 중복을 줄이고 유지보수를 쉽게 해주며, IS-A 관계를 코드로 표현할 수 있다. 단, 단일 상속만 가능하고(final 포함) override 규칙을 정확히 이해한 상태에서 사용하는 것이 중요하다.