<상속>
- 상속의 정의
**상속(Inheritance)**은 부모(상위) 클래스의 필드와 메서드를 자식(하위) 클래스가 물려받아 재사용하는 것이다. 객체 생성 시 부모 부분 → 자식 부분 순으로 메모리에 구성되며, 자식 객체 내부에 부모 객체가 존재하는 것처럼 실행된다.
- 상속의 장점
- 재사용성/생산성: 코드를 재사용하여 새로운 클래스를 정의할 수 있다
- 유지보수성: 공통 코드를 상위 클래스에 두어 변경이 용이하다
- 확장성: 하위 클래스에서 오버라이딩으로 동작을 재정의할 수 있다
- 상속의 특징
- 단일 상속: 다중 상속은 불가능하다 (부모는 하나)
- Object 클래스: 모든 클래스는 Object라는 최상위 클래스를 상속받는다
- 접근 범위: 오버라이딩 시 접근 범위는 축소할 수 없다
ex: Man과 BusinessMan
- 부모 클래스: Man
package com.kh.inherit;
public class Man {
private String name;
protected Man() {
super();
System.out.println("Man의 기본생성자");
}
protected Man(String name) {
super();
this.name = name;
System.out.println("Man에 name이 포함된 생성자");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void tellYourName() {
System.out.println("My name is " + name);
}
}
- 자식 클래스: BusinessMan
package com.kh.inherit;
public class BusinessMan extends Man {
private String company;
private String position;
protected BusinessMan(String name, String company, String position) {
super(name); // 자식클래스의 생성자에는 무조건 부모생성자가 필요
// 맨 첫번째 줄에, 생략 시 부모의 기본 생성자를 호출
this.company = company;
this.position = position;
}
public void tellYourInfo() {
System.out.println("My company is " + company);
System.out.println("My Position is " + position);
super.tellYourName(); // super. -> 부모클래스의 메모리에 접근
}
}
- super 키워드의 활용
super 키워드는 부모 클래스의 요소에 접근할 때 사용한다:
- super(): 부모 클래스의 생성자 호출
- super.method(): 부모 클래스의 메서드 호출
- super.field: 부모 클래스의 필드 접근
Product 상속 구조 - 제품 관리 시스템
- 부모 클래스: Product
package com.kh.inherit;
public class Product {
private String pName;
private int price;
private String brand;
protected Product() {
super();
}
protected Product(String pName, int price, String brand) {
super();
this.pName = pName;
this.price = price;
this.brand = brand;
}
// Getter, Setter 메서드들
public String getpName() {
return pName;
}
public void setpName(String pName) {
this.pName = pName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
// 제품 정보 출력 메서드
public String inform() {
return "상품명 : " + pName + " / 가격 : " + price + " / 브랜드 : " + brand;
}
}
- 자식 클래스: Desktop
package com.kh.inherit;
public class Desktop extends Product {
private boolean isAllInOne;
public Desktop() {
// 부모의 기본 생성자가 자동 호출
}
public Desktop(String pName, int price, String brand, boolean isAllInOne) {
super(pName, price, brand); // 부모 생성자 명시적 호출
this.isAllInOne = isAllInOne;
}
public boolean isAIO() {
return isAllInOne;
}
public boolean isAllInOne() {
return isAllInOne;
}
public void setAllInOne(boolean isAllInOne) {
this.isAllInOne = isAllInOne;
}
// 오버라이딩: 부모의 inform() 메서드를 재정의
public String inform() {
return "상품명 : " + super.getpName() + " / 가격 : " + super.getPrice() +
" / 브랜드 : " + super.getBrand() + " / 일체형 여부 : " +
(isAllInOne ? "일체형" : "따로따로");
}
}
- 자식 클래스: TV
package com.kh.inherit;
public class TV extends Product {
private int inch;
public TV() {
super(); // 부모의 기본 생성자 호출
}
public TV(String pName, int price, String brand, int inch) {
super(pName, price, brand); // 부모의 매개변수 생성자 호출
this.inch = inch;
}
public int getInch() {
return inch;
}
public void setInch(int inch) {
this.inch = inch;
}
// TV 클래스는 부모의 inform() 메서드를 그대로 사용
}
상속 실행 및 테스트
- 상속 관계 테스트
package com.kh.inherit;
import java.util.Scanner;
public class Run {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// Man 객체 생성
Man m1 = new Man("IAhn");
// BusinessMan 객체 생성
BusinessMan m2 = new BusinessMan("IAhn", "hth_sm", "dancer");
m2.tellYourInfo();
m2.tellYourName(); // 부모 클래스의 메서드 호출
// 잘못된 할당 (컴파일 에러)
// BusinessMan m3 = new Man(); // 자식의 참조변수에 부모객체를 생성할 수는 없다
// Product 상속 구조 테스트
Desktop d1 = new Desktop();
Desktop d2 = new Desktop("d-100", 1000000, "samsung", true);
TV t1 = new TV("t-100", 1000000, "samsung", 14);
System.out.println(t1.inform()); // 부모의 inform() 메서드 사용
System.out.println(d2.inform()); // 오버라이딩된 inform() 메서드 사용
}
}
실행 결과:
Man에 name이 포함된 생성자
Man에 name이 포함된 생성자
My company is hth_sm
My Position is dancer
My name is IAhn
상품명 : t-100 / 가격 : 1000000 / 브랜드 : samsung
상품명 : d-100 / 가격 : 1000000 / 브랜드 : samsung / 일체형 여부 : 일체형
<오버라이딩>
- 오버라이딩의 정의
**오버라이딩(Overriding)**은 부모 클래스에 있는 메서드를 하위 클래스에서 내용만 재정의하는 것이다.
- 오버라이딩의 조건
- 메서드 이름: 부모와 동일해야 한다
- 매개변수: 타입, 개수, 순서가 모두 동일해야 한다
- 반환형: 부모와 동일하거나 하위 타입이어야 한다
- 접근 제한자: 부모보다 좁은 범위로 변경할 수 없다
- 오버라이딩 vs 오버로딩
구분 오버라이딩(Overriding) 오버로딩(Overloading)
| 관계 | 상속 관계 | 같은 클래스 내 |
| 메서드명 | 동일 | 동일 |
| 매개변수 | 동일 | 다름 |
| 목적 | 기능 재정의 | 기능 확장 |
상속에서의 생성자 호출 순서
- 생성자 호출 메커니즘
public class InheritanceTest {
public static void main(String[] args) {
System.out.println("=== BusinessMan 객체 생성 ===");
BusinessMan bm = new BusinessMan("김개발", "테크회사", "개발자");
}
}
실행 과정:
- BusinessMan 생성자 호출
- super(name) → Man 생성자 호출
- Man 생성자에서 super() → Object 생성자 호출 (자동)
- Object → Man → BusinessMan 순으로 객체 구성 완료
- 메모리 구조
[BusinessMan 객체]
├── [Man 부분]
│ ├── name: "김개발"
│ └── tellYourName() 메서드
├── company: "테크회사"
├── position: "개발자"
└── tellYourInfo() 메서드
- 상속은 부모 클래스의 필드와 메서드를 자식 클래스가 재사용하는 메커니즘이다
- extends 키워드를 사용하여 상속 관계를 설정한다
- super 키워드를 통해 부모 클래스의 생성자와 메서드에 접근할 수 있다
- 오버라이딩을 통해 부모 메서드의 동작을 재정의할 수 있다
- 자식 클래스 생성 시 부모 생성자가 먼저 호출된다
'Java' 카테고리의 다른 글
| Java_14) Garbage Collection (1) | 2025.11.11 |
|---|---|
| Java_13) 오버로딩과 오버라이딩 (0) | 2025.11.10 |
| Java_11) Access Modifier, ObjectArray (1) | 2025.08.27 |
| Java_10) Class - 객체 (Object) (4) | 2025.08.27 |
| Java_09) Method (4) | 2025.08.27 |