상속 ( Inheritance )
상속은 OOP ( 객체지향 프로그래밍 ) 핵심 개념 중 하나이다.
즉, 상속은 자료형 / 문법 같은 "언어 요소" 가 아니라, 객체지향 프로그래밍 패러다임의 핵심 네 가지 축 중 하나에 해당된다.
객체지향 프로그래밍 ( OOP ) 에서 상속은 코드의 재사용성과 확정성을 높이기 위한 핵심 개념이다.
C# 에서는 상속을 통해 기존 클래스의 기능을 물려받고, 필요에 따라 추가하거나 수정할 수 있다.
상속을 하면 기존 클래스 ( 부모 , 또는 기반 클래스 ) 의 변수 , 메서드 등을 새로운 클래스 (자식 , 파생 클래스) 에서 사용 가능하다.
클래스의 경우라면 상속은 다중 상속을 지원하지 않는다.
예외적으로 인터페이스 ( Interface ) 의 경우는 여러가지를 구현 가능하다.
문법
class 부모클래스
{
// 필드, 메서드 등 공통 기능 정의
}
class 자식클래스 : 부모클래스
{
// 추가 또는 재정의 기능
}
class Character
{
public string name;
public void Move()
{
Console.WriteLine($"{name}이(가) 이동합니다.");
}
}
class Warrior : Character
{
public void Attack()
{
Console.WriteLine($"{name}이(가) 공격합니다!");
}
}
class Healer : Character
{
public void Heal()
{
Console.WriteLine($"{name}이(가) 힐을 줍니다!");
}
}
Warrior w = new Warrior();
w.name = "호찬";
w.Move(); // 부모 클래스의 메서드
w.Attack(); // 자식 클래스의 메서드
Healer h = new Healer();
w.name = "향숙";
w.Move(); // 부모 클래스의 메서드
w.Heal(); // 자식 클래스의 메서드
▲Warrior 와 Healer 는 Character 를 상속받아 Move() 를 사용할 수 있다
자신만의 기능인 Attack() 과 Heal() 도 가질수 있다.
주의할 점
- 캡슐화 주의 : 부모 클래스의 private 멤버는 자식 클래스에서 접근 불가능하다.
- 생성자 상속 : 부모 생성자는 자동 상속되지 않으며 , 필요시 base() 로 호출해야 한다.
- 다형성 : virtual , override , new 키워드로 메서드 재정의 시 주의해야 한다.
- 다중 상속 불가 : 인터페이스 ( Interface ) 로 보완해야 한다.
base 사용 예시
자식 클래스 내부에서 base() 키워드를 사용하면 부모 클래스의 생성자나 메서드에 접근 가능하다.
당연히 public , protected 등 접근제한자로 선언된 필드에도 접근할 수 있다.
▼부모 생성자 호출
class Person
{
public string Name;
// 부모 생성자
public Person(string name)
{
Name = name;
Console.WriteLine("Person 생성자 호출");
}
}
class Student : Person
{
public int Grade;
// 자식 생성자에서 base()로 부모 생성자 호출
public Student(string name, int grade) : base(name)
{
Grade = grade;
Console.WriteLine("Student 생성자 호출");
}
}
class Program
{
static void Main()
{
Student s = new Student("호찬", 3);
Console.WriteLine($"{s.Name}, {s.Grade}학년");
}
}
▼출력
Person 생성자 호출
Student 생성자 호출
호찬, 3학년
base(name) 덕분에 부모 클래스의 Name 필드도 올바르게 초기화
▼부모 메서드 호출
class Animal
{
public virtual void Speak()
{
Console.WriteLine("동물이 소리를 냅니다.");
}
}
class Dog : Animal
{
public override void Speak()
{
base.Speak(); // 부모의 Speak 먼저 실행
Console.WriteLine("멍멍!");
}
}
class Program
{
static void Main()
{
Dog dog = new Dog();
dog.Speak();
}
}
▼출력
동물이 소리를 냅니다.
멍멍!
base.Speak() 를 통해 부모 클래스의 동작을 유지하면서 자식에서 기능 확장
주의할 점
base() 는 반드시 부모 생성자가 존재해야 호출할 수 있다.
생성자에서 this() 와 base()를 동시에 사용할 수는 없다. ( 둘 중 하나만 가능하다 )
메서드에서 base.Method() 를 쓰면 부모의 구현을 강제 실행하는 것이므로 다형성 구조 설계시 의도적으로 써야한다.
상속을 사용하면 좋은 상황
1. 공통 기능을 여러 클래스에서 공유할 때
중복된 코드를 줄이고 싶을 때 사용한다.
예시 : Player , Enemy , NPC 가 모두 Move() 메서드를 가진다면 Character 라는 부모 클래스를 만들어 상속
2. 다형성이 필요할 때
부모 클래스 참조로 여러 자식 객체를 다루고 싶을 때
List<Animal> animals = new List<Animal>();
animals.Add(new Dog());
animals.Add(new Cat());
foreach (var a in animals)
a.Speak(); // 다형성 덕분에 각각 다른 동작 실행
3. 확장 가능한 구조를 만들고 싶을 때
앞으로 새로운 기능을 추가하거나 클래스를 확장할 가능성이 있을 때 사용하면 좋다
예시 : 게임에서 새로운 Monster 종류를 계속 추가해야 한다면 Monster 부모 클래스를 두고 확장하는게 좋다
주의할 점
- 단순히 코드 재사용만들 위해 상속을 남용하면 유지 보수가 힘들고 부모 클래스 변경이 전체 자식에 영향을 미친다.
- 부모와 자식의 관계가 애매하다 면 상속보다 인터페이스나 컴포지션을 고려
- 깊은 상속 구조 ( 3단계 이상 )는 가독성과 관리가 어려워지므로 지양하자.
정리
상속 : 부모 클래스의 기능을 자식 클래스가 물려받아 재사용하고 확장할 수 있게 해주는 OOP 핵심 개념
base : 자식 클래스에서 부모 생성자나 메서드를 명시적으로 호출해 부모의 초기화 또는 동작 활용
참고 자료
https://learn.microsoft.com/ko-kr/dotnet/csharp/fundamentals/tutorials/inheritance
'⭐C Sharp > 11. 객체 지향' 카테고리의 다른 글
| virtual 과 override (0) | 2025.10.08 |
|---|---|
| readonly (0) | 2025.10.02 |
| 추상 클래스 ( Abstract Class ) (0) | 2025.09.28 |
| 인터페이스 ( Interface ) (0) | 2025.09.28 |
| this ( 매개변수 키워드 ) (0) | 2025.09.28 |