🔍 오늘의 학습 주제
객체지향 프로그램 개념, 클래스 구성, 상속과 다형성 깊게 이해하기
🧠 OOP의 5대 특징
개념 설명 비유/예시
| 캡슐화 | 데이터 + 기능을 하나로 묶고, 외부에는 필요한 정보만 공개 | 약을 하나의 캡슬에 달아넣는 것 |
| 상속 | 기존 클래스를 바탕으로 새 클래스 생성 | Monster → Goblin, Dragon |
| 다형성 | 같은 메서드 이름이 상황에 따라 다른 동작 | Attack() → 고블린은 칼, 드래곤은 불 |
| 추상화 | 내부 구조는 숨기고 필요한 기능만 외부에 공개 | 스마트폰 인터페이스처럼 내부 작동은 숨기고 터치만 가능 |
| 객체 | 클래스의 실체. 상태 + 동작 가지는 것 | goblin, merchant 같은 구체 |
🔹 클래스와 인스턴스
class Monster {
public string Name;
public int HP;
public void Attack() {
Console.WriteLine($"{Name}이(가) 공격합니다!");
}
}
Monster goblin = new Monster();
goblin.Name = "고블린";
goblin.HP = 30;
goblin.Attack();
✅ 클래스는 객체를 만들기 위한 설계도. 위 코드에서 Monster는 이름(Name), 체력(HP), 공격 기능(Attack)을 가진 클래스다.
✅ goblin은 Monster 클래스를 바탕으로 만들어진 인스턴스로, 메모리에 실제로 존재하는 실체!
✅ 인스턴스를 통해 필드에 값을 저장하거나, 메서드를 호출할 수 있다
🔹 접근 제한자 (Access Modifiers)
제한자 설명
| public | 외부 클래스나 코드에서 자유롭게 접근 가능 |
| private | 선언된 클래스 내부에서만 접근 가능 (외부에서 접근 불가) |
| protected | 자식 클래스(상속 관계)에서 접근 가능 (외부 클래스에서는 접근 불가) |
✅ 접근 제한자는 클래스 멤버의 **가시성(접근 가능 범위)**을 제어.
- 외부 접근이 필요한 경우 public
- 클래스 내부에서만 써야 할 때는 private
- 자식 클래스까지 공유하고 싶은 경우 protected → 이는 **캡슐화(Encapsulation)**를 구현하는 핵심 도구
🔹 필드와 메서드
class NPC {
public string Name;
private string Dialogue;
public void Talk() {
Console.WriteLine($"{Name}: {Dialogue}");
}
public void SetDialogue(string text) {
Dialogue = text;
}
}
✅ **필드(Field)**는 클래스 내부에 데이터를 저장하는 변수. 위 예시에서 Name, Dialogue가 필드.
✅ public 필드인 Name은 외부에서 직접 접근 가능
✅ private 필드인 Dialogue는 외부에서 접근할 수 없어 SetDialogue() 메서드를 통해 설정
✅ **메서드(Method)**는 클래스에 정의된 함수로, 객체의 행동이나 기능을 구현 → 필드와 메서드를 통해 객체의 **상태(state)**와 **동작(behavior)**을 구분하여 정의
🔹 생성자와 소멸자
class Enemy {
public string Name;
public int HP;
// 생성자(Constructor)
public Enemy(string name, int hp) {
Name = name;
HP = hp;
Console.WriteLine($"{Name}이(가) 생성되었습니다! HP: {HP}");
}
// 소멸자(Destructor)
~Enemy() {
Console.WriteLine($"{Name}이(가) 소멸됩니다.");
}
}
Enemy slime = new Enemy("슬라임", 20); // 생성자 호출됨
✅ **생성자(Constructor)**는 객체가 생성될 때 자동으로 호출되는 특별한 메서드
- 클래스 이름과 동일하며 반환형이 없다.
- 주로 필드 초기화나 생성 직후 로직을 넣는다.
✅ **소멸자(Destructor)**는 객체가 메모리에서 제거될 때 자동 호출됩니다.
- ~클래스명() 형식이며, 주로 리소스 해제 또는 로그 출력 등에 사용
- C#에서는 가비지 컬렉터에 의해 호출되므로, 명시적 호출은 불가능
🔹 프로퍼티 (Property)
class Hero {
private int hp;
public int HP {
get { return hp; }
set {
if (value >= 0) hp = value;
}
}
}
Hero knight = new Hero();
knight.HP = -10; // 무시됨
Console.WriteLine(knight.HP); // 출력: 0
✅ **프로퍼티(Property)**는 필드에 대한 접근을 제어하는 방법
- 외부에서는 필드처럼 보이지만, 내부적으로는 get/set 메서드가 작동
- 위 코드에서는 0 미만의 값은 설정되지 않도록 제한되어 있다.
🔹 자동 프로퍼티 (Auto Property)
class Item {
public string Name { get; set; }
public int Price { get; set; }
}
Item potion = new Item { Name = "포션", Price = 50 };
Console.WriteLine($"{potion.Name}: {potion.Price}골드");
✅ 자동 프로퍼티는 별도의 필드 선언 없이 간단하게 get/set 기능을 제공할 수 있게 해준다.
- 컴파일러가 내부에서 자동으로 backing field를 생성.
- 주로 간단한 데이터 객체(Data Object)나 설정 객체에서 유용하게 쓰인다
🔹 상속과 다형성
// 부모 클래스
public class Animal
{
public string Name { get; set; }
public void Eat()
{
Console.WriteLine("먹이를 먹습니다.");
}
}
// 자식 클래스
public class Dog : Animal
{
public void Bark()
{
Console.WriteLine("멍멍!");
}
}
Dog dog = new Dog();
dog.Name = "초코";
dog.Eat(); // 부모 클래스의 메서드 사용 가능
dog.Bark(); // 자식 클래스 고유 메서드
✅ **상속(Inheritance)**은 기존 클래스(부모)를 기반으로 새로운 클래스(자식)를 만드는 방식
- 자식 클래스는 부모 클래스의 필드와 메서드를 물려받을 수 있다.
- 코드 재사용성을 높이고 계층 구조를 명확하게 만들 수 있다.
// 다형성 예시
public class Unit
{
public virtual void Move()
{
Console.WriteLine("두 발로 이동");
}
}
public class Marine : Unit { }
public class Zergling : Unit
{
public override void Move()
{
Console.WriteLine("네 발로 이동");
}
}
List<Unit> units = new List<Unit>();
units.Add(new Marine());
units.Add(new Zergling());
foreach (Unit unit in units)
{
unit.Move(); // 같은 타입으로 묶어도 실제 동작은 다르게!
}
✅ **다형성(Polymorphism)**은 같은 타입의 객체가 서로 다른 동작을 수행할 수 있게 한다.
- 부모 클래스를 참조하더라도 자식 클래스의 오버라이딩된 메서드가 호출
- virtual, override 키워드를 사용하여 구현
✅ 추상 클래스 (Abstract Class)
abstract class Shape
// 추상 메서드는 자식 클래스에서 추상 선언된 메서드를 반드시(강제적으로) 구현해야 한다. override 키워드를 사용하여 구현한다.
//또한, 추상 클래스는 인스턴스를 만들 수 없다.
{
public abstract void Draw();
}
class Circle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a circle");
}
}
class Square : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a square");
}
}
class Triangle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a triangle");
}
}
static void Main(string[] args)
{
// Shape shape = new Shape(); 오류: 추상 클래스는 인스턴스를 만들 수 없다.
List<Shape> list = new List<Shape>();
list.Add(new Circle());
list.Add(new Square());
list.Add(new Triangle());
// 다형성: 부모 클래스의 참조 변수를 통해 자식 클래스의 메서드를 호출할 수 있다.
foreach (Shape shape in list)
{
shape.Draw();
}
}
✅ 추상 클래스는 직접 인스턴스를 만들 수 없으며, 반드시 상속하여 사용한다.
- 하나 이상의 **추상 메서드(abstract)**를 포함할 수 있으며,
- 자식 클래스에서 반드시 override로 구현(강제성)
- 공통 동작은 구현하고, 차이는 강제할 때 사용
✅ 오버라이딩 (Overriding)
public class Shape {
public virtual void Draw() {
Console.WriteLine("Drawing a shape.");
}
}
public class Circle : Shape {
public override void Draw() {
Console.WriteLine("Drawing a circle.");
}
}
public class Rectangle : Shape {
public override void Draw() {
Console.WriteLine("Drawing a rectangle.");
}
}
Shape shape1 = new Circle();
Shape shape2 = new Rectangle();
shape1.Draw(); // Drawing a circle.
shape2.Draw(); // Drawing a rectangle.
✅ 오버라이딩은 부모 클래스의 메서드를 자식 클래스에서 재정의하는 것이다.
- 메서드의 이름, 매개변수, 반환 타입이 모두 같아야 한다.
- 자식 클래스가 부모의 동작을 자기 방식대로 바꾸고 싶을 때 사용
✅ 오버로딩 (Overloading)
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
public int Add(int a, int b, int c)
{
return a + b + c;
}
}
Calculator calc = new Calculator();
int result1 = calc.Add(2, 3); // 5
int result2 = calc.Add(2, 3, 4); // 9
✅ 오버로딩은 이름은 같지만 매개변수(개수, 타입, 순서)가 다른 메서드를 여러 개 정의하는 것.
- 하나의 이름으로 다양한 입력을 처리하고 싶을 때 사용
🔸 회고 및 정리
이번 주는 클래스라는 개념에 깊게 들어갔던 한 주였다. 클래스는 생각보다 간단한 구조 같으면서도 실제로 쓰려면 복잡한 규칙이 많았고, 완전히 이해하는 데 이틀이나 걸렸다.
특히 객체지향 5대 특성 중에서 '캡슐화'와 '다형성'은 처음엔 추상적으로 느껴졌지만, 직접 코드를 작성하며 점점 감이 잡히기 시작했다. 예제에서 몬스터를 만들고, NPC를 구현해보면서 클래스가 단순히 데이터 묶음이 아니라 '행동을 포함하는 틀'이라는 걸 체감하게 되었다.
get/set, 생성자, 소멸자, 프로퍼티 등은 아직 익숙하진 않지만, 쓰는 방식보단 왜 필요한지를 먼저 이해하려고 노력했다. 그 점에서 이번 학습은 단순한 외우기가 아닌 '이해 기반의 숙련'을 위한 좋은 시작이었다고 생각한다.
내일은 오늘 복습을 통해 클래스와 프로퍼티에 대한 감을 더욱 다지고, 간단한 텍스트 RPG에 이를 응용해보는 실습 위주로 진행할 예정이다.
'팀스파르타 코딩' 카테고리의 다른 글
| 📘내일의 학습 목표: 인터페이스와 열거형 (1) | 2025.04.15 |
|---|---|
| 🧠2025년 4월 15일 (월) / C# 객체지향 심화용 - 제너릭과 out, ref 키워드 (0) | 2025.04.15 |
| 📚 내일의 학습 목표 - 클래스와 객체 (C#) (0) | 2025.04.14 |
| 📚 TIL - 2025년 4월 14일 (월) / C# 입문 일지 (배열, 컬렉션, 메서드, 구조체) (0) | 2025.04.14 |
| 📚 TIL - 2025년 4월 13일 (일) / C# 입문 일지 (0) | 2025.04.13 |