1. 상속(Inheritance) 개념
상속(Inheritance)은 객체 지향 프로그래밍(OOP)의 핵심 개념으로, 기존 클래스를 기반으로 새로운 클래스를 만드는 방법이다.
1-1. 상속의 특징
- 코드 재사용
: 부모 클래스에서 정의된 속성과 메서드를 자식 클래스에서 재사용 - 확장성
: 자식 클래스는 부모 클래스의 기능을 확장하거나 변경(`@Override`)할 수 있다. - 계층적 구조
: 클래스 간의 관계를 계층적으로 설계하여 프로그램 구조를 체계적으로 만들 수 있다. - 단일 상속
: Java는 클래스의 다중 상속을 지원하지 않으며, 하나의 부모 클래스만 상속받을 수 있다.
(인터페이스를 통해 다중 상속과 유사한 기능 구현 가능)
1-2. 상속의 용어
- 부모 클래스 (Parent Class)
- 상속을 제공하는 클래스
- 기본 기능(필드와 메서드)을 정의
- 슈퍼클래스(Superclass)라고도 불림
- 자식 클래스 (Child Class)
- 부모 클래스를 상속받아 기능을 재사용하거나 확장하는 클래스
- 서브클래스(Subclass)라고도 불림
1-3. 상속의 구현
`extends` 키워드를 사용하여 구현된다.
class Parent {
void showMessage() {
System.out.println("부모 클래스 메서드");
}
}
class Child extends Parent {
void display() {
System.out.println("자식 클래스 메서드");
}
}
1-4. 메서드 오버라이딩 (Method Overriding)
자식 클래스에서 부모 클래스의 메서드를 재정의(overriding)하여 동작을 변경할 수 있다.
class Animal {
void sound() {
System.out.println("This animal makes a sound.");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("The dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Dog(); // 부모 타입 참조, 자식 객체 생성
animal.sound(); // 오버라이딩된 메서드 호출
}
}
- `@Override` 어노테이션은 부모 클래스의 메서드를 자식 클래스에서 재정의했음을 명시한다.
1-5. 상속의 제한
`final` 키워드
- 클래스에 붙이면 해당 클래스는 상속될 수 없다.
- 메서드에 붙이면 해당 메서드는 오버라이딩 할 수 없다.
다중 상속 불가
- Java는 클래스 간 충돌 문제 방지를 위해 다중 상속을 지원하지 않는다.
- 대신 인터페이스를 통해 다중 상속처럼 구현이 가능하다.
1-6. 상속의 장점/단점
장점
- 코드 재사용성: 부모 클래스의 코드를 재사용하여 중복 제거
- 유지보수성: 수정해야 할 코드가 부모 클래스에 집중됨
- 확장성: 기존 클래스에 새로운 기능을 쉽게 추가 가능
단점
- 종속성 증가: 자식 클래스가 부모 클래스에 의존하기 때문에 변경 시 영향을 받을 수 있음
- 복잡성 증가: 깊은 상속 구조는 코드의 가독성을 떨어뜨림
2. 다형성(Polymorphism)의 개념
다형성(Polymorphism)은 객체 지향 프로그래밍(OOP)의 중요한 특징 중 하나로, 동일한 메서드 호출이 객체의 타입에 따라 다르게 동작하도록 구현하는 것을 의미한다.
2-1. 다형성의 핵심 개념
컴파일 타임 다형성 (Compile-Time Polymorphism)
- 메서드 오버로딩(Method Overloading)을 통해 구현
- 같은 이름의 메서드를 여러 개 정의하고, 매개변수의 타입이나 개수에 따라 호출이 결정된다.
런타임 다형성 (Run-Time Polymorphism)
- 메서드 오버라이딩(Method Overriding)을 통해 구현
- 부모 클래스의 참조 변수로 자식 클래스 객체를 참조하여 실행 시점에 실제 객체의 메서드가 호출된다.
특징 | 컴파일 타임 다형성 | 런타임 다형성 |
구현 방식 | 메서드 오버로딩 | 메서드 오버라이딩 |
결정 시점 | 컴파일 시점 | 실행 시점 |
유연성 |
낮음 | 높음 |
런타임에 객체 타입에 따라 동작을 다르게 처리할 수 없다. 정적으로 매개변수의 타입이나 개수에 따라 메서드가 호출되므로, 동적 객체의 동작에는 부적합 |
부모 클래스 타입으로 다양한 자식 객체를 처리할 수 있으므로, 실행 시점에서 객체의 실제 타입에 따라 다른 동작을 수행한다. | |
속도 |
빠름 | 느림 |
컴파일 시점에 호출할 메서드가 결정되기 때문에, 런타임 다형성보다 실행속도가 빠름 | 메서드 호출 시, 런타임에 객체의 실제 타입을 확인하고 메서드를 호출해야하기 때문에 컴파일 타임 다형성보다 느림 | |
상속 필요 여부 | 상속 불필요 | 상속 필수 |
적용 시점 | 동일 클래스 내에서 구현 가능 | 부모-자식 클래스 간에 구현 가능 |
확장성 |
제한적 | 높음 |
클래스 간 계층 구조나 상속과 무관하게 동작하기 때문에 상속 기반의 확장을 못함 | 새로운 자식 클래스를 추가해도 기존 코드를 수정하지 않고 동작을 확장할 수 있다. |
2-2. 다형성 구현
메서드 오버로딩
class Calculator {
int add(int a, int b) {
return a + b;
}
// 오버로딩: 매개변수의 개수가 다름
int add(int a, int b, int c) {
return a + b + c;
}
// 오버로딩: 매개변수의 타입이 다름
double add(double a, double b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(2, 3)); // 정수 덧셈
System.out.println(calc.add(2, 3, 4)); // 세 개의 정수 덧셈
System.out.println(calc.add(2.5, 3.5)); // 실수 덧셈
}
}
- 같은 이름의 메서드 `add`가 여러 개 정의되어 있지만, 매개변수의 타입이나 개수에 따라 실행되는 메서드가 선택된다.
- 컴파일 시점에 어떤 메서드가 호출될지 결정되므로 컴파일 타임 다형성이라고 한다.
메서드 오버라이딩
1-4. 메서드 오버라이딩 참고.
- 실행 시점에 어떤 메서드가 호출될지 결정되므로 런타임 다형성이라고 한다.
'TIL (Today I Learned)' 카테고리의 다른 글
[TIL] SQL - WITH RECURSIVE 개념과 사용법 (0) | 2025.02.06 |
---|---|
[TIL] SQL 윈도우 함수 (Window Function) (0) | 2025.01.14 |
[Java] 예외 처리 방법: 기본 구조, throw/throws, 사용자 정의 예외 (1) | 2025.01.10 |
[Java] 스택 자료구조: Stack과 Deque 비교 (0) | 2025.01.10 |
[TIL] Java 계산기 만들기 과제 회고 🤓✏️ (2) | 2025.01.09 |