CSharp 클래스(Class)

양승준·2025년 4월 6일

CSharp

목록 보기
15/20
post-thumbnail

시작하며

객체지향 코드인 C#의 핵심인 class를 드디어 오늘 정리하고자한다.


객체지향 프로그래밍(Object-Oriented Programming, OOP)

객체란?

  • 객체(Object)는 물건, 물체를 의미하며, 특정 실체를 '객관화' 하여 인식하거나 이해하는 대상이다.
  • 객체는 속성과 행동을 가지며, 현실 세계의 사물 또는 개념을 소프트웨어로 표현한 것이라 할 수 있다.

예시

  • 🚗 자동차 → 객체
  • 🍞 붕어빵 → 객체
  • 📖 교과서 → 객체



객체지향 프로그래밍이란?

현실 세계의 객체들을 프로그래밍에 반영하여 데이터(속성)기능(행동)을 하나의 단위로 묶어 개발하는 프로그래밍 패러다임이다.

💡 핵심 특징

특징설명
캡슐화관련 있는 데이터와 메서드를 묶고 외부에 숨김
상속기존 클래스의 기능을 새로운 클래스에 물려줌
다형성같은 이름의 메서드가 다양한 방식으로 동작
추상화불필요한 정보는 숨기고 핵심만 표현


클래스

클래스(Class)란?

  • 클래스는 객체를 생성하기 위한 설계도 또는 틀이다.
  • 객체는 클래스로부터 생성된 인스턴스(instance)이다.
  • 클래스에는 필드(속성), 메서드(기능), 생성자, 이벤트 등을 정의할 수 있다.
public class Car
{
    public string Model;
    public void Drive()
    {
        Console.WriteLine($"{Model}이(가) 달립니다.");
    }
}

static void Main(string[] args)
{
    // main 함수에서 사용 코드
    Car myCar = new Car(); // new 키워드로 생성자 사용
    myCar.Model = "소나타"; // 내부의 외부 공개 가능한 값에 접근 및 값 할당
    myCar.Drive(); // 내부의 외부 공개 가능한 함수 기능 사용
}

소나타이(가) 달립니다.


생성자

생성자는 클래스구조체인스턴스를 생성할 때 자동으로 호출되는 특수한 메서드이다.

생성자의 주요 역할

생성자는 객체의 초기화는 생성자의 가정 핵심 역할이다. 필드나 속성을 객체가 생성될 때 원하는 초기값으로 생성 할 수 있다.

class Player
{
    public string Name;
    public int HP;

    public Player(string name)
    {
        Name = name;
        HP = 100;  // 기본 체력
    }
}

인스턴스

  • 영어적 인스턴스(Instance): 어떤 것의 구체적인 예, 사례
    인스턴스화를 했다 > 실체화된 사례, 구체적인 예시

  • 프르래밍적 인스턴스(Instance): 클래스로(설계도)부터 만들어진 하나의 구체적인 객체(실체)


객체 생성 시점에 필요한 로직 수행

플레이어 이름 초기화, 기본 체력 설정, 플레이어 초기화 문구 출력 등을 넣어서 객체가 생성될 때 필요한 작업을 수행 할 수 있다.

class Player
{
    public string Name;
    public int HP;

    public Player(string name)
    {
        Name = name;
        HP = 100;  // 기본 체력
        Console.WriteLine("플레이어 초기화됨!"); // 로직 수행!!
    }
}



오버로딩으로 다양한 초기화 옵션 제공

동일한 이름으로 매개변수만 다른 생성자 여러 개를 만들 수 있다. 사용자가 상황에 따라 적절한 생성자를 선택하여 사용가능하다.

class Player
{
    public string Name;
    public int HP;

	public Player()
    {
	    Name = "None"; // 기본 이름
        HP = 100;  // 기본 체력
        InitPrint(); // 출력
    }
    
    public Player(string name)
    {
        Name = name;
        HP = 100;  // 기본 체력
        InitPrint();
    }
	
    public Player(string name, int hp)
    {
        Name = name;
        HP = hp;
        InitPrint();
    }
    
    private void InitPrint()
    {
    	Console.WriteLine("플레이어 초기화됨!");
        Console.WriteLine($"플레이어 이름: {Name}");
        Console.WriteLine($"플레이어 이름: {HP}");
    }
}

오버로딩

  • 동일한 이름으로 매개변수만 및 반환 타입을 다르게 하여 여러게의 메소드 정의 할 수 있는 문법


클래스 상속 시 부모 클래스 초기화

자식 클래스가 생성될 때, 먼저 부모 클래스의 생성자가 호출되어 초기화 된다. (생성자 실행순서 : 부모 > 자식 > 손자)
base() 키워드로 명시적으로 호출할 수도 있다.

class Animal
{
    public Animal(string name)
    {
        Console.WriteLine($"{name} 동물이 생성됨!");
    }
}

class Dog : Animal
{
    public Dog() : base("강아지") { }
}



불변 객체 생성

이전에 상수관련해서 정리 하지 않았는가? 그것을 활용하여 생성자를 활용하는 것. 생성자를 통해서 필드를 설정하고, 이후에는 수정하지 못하도록 만드는 패턴이다.(상수 관련해서 봤으면 또 보는 이야기 일 것이다)

class ImmutableItem
{
    public readonly int Id;
    public readonly string Name;

    public ImmutableItem(int id, string name)
    {
        Id = id;
        Name = name;
    }
}



💡 생성자 요약

역할설명
객체 초기화필드나 속성을 원하는 값으로 설정
초기화 로직 수행생성 시점에 필요한 작업 수행 (ex. 로깅, 파일열기 등)
생성자 오버로딩다양한 초기 상태를 만들 수 있도록 여러 생성자 제공
상속 시 부모 초기화자식 생성자에서 부모 생성자 호출하여 초기화 수행
불변 객체 생성readonly 필드를 생성자에서만 설정하여 외부 변경 차단





상속

상속? 뉴스 같은 곳에서 가끔 들려오는 단어이다. 기존의 제산 같은 것들을 자식에게 물려주기 위한 행동을 뜻한다. 프로그래밍에서도 비슷하다.

상속은 기존 클래스(부모, 상위 클래스, 기반 클래스) 의 필드, 메서드, 속성 등을 새로운 클래스(자식, 부 클래스, 파생 클래스) 가 물려받는 기능이다.

이렇게 물려줘, 클래스 간의 종속 관계를 만듦으로서 객체를 조직화 할 수 있다.

상속의 핵심은 재사용과 확장의 기반이라고 할 수 있다.

C# 의 상속 특징

  • 단일 상속만 허용(여러 클래스에서 동시에 상속 불가)
  • 인터페이스는 다중 구현 가능
  • 생성자는 상속되지 않음, 하지만 base()로 호출 가능
  • 구조체(struct)는 상속할 수 없음(인터페이스 구현만 가능)

추상 클래스

클래스를 만들다 보면, 공통 구조는 같지만, 구체적인 동작은 자식 클래스가 구현해야 할 때 사용한다. 이때 사용하는 것이 추상 클래스다.

  • 객체 생성 불가
  • 공통 로직 구현 + 자식이 구현할 함수 선언 (추상 메서드)

특징 비교

항목추상 클래스일반 클래스
인스턴스 생성불가가능
추상 메서드 정의가능불가
일부 구현 포함가능가능
목적공통 + 확장구체적 구현

예제

abstract class Animal
{
    public string Name { get; set; }

    public Animal(string name)
    {
        Name = name;
    }

    public void Sleep()
    {
        Console.WriteLine($"{Name}이(가) 잠을 잡니다.");
    }

    // 추상 메서드: 자식 클래스가 반드시 구현해야 함
    public abstract void MakeSound();
}

class Dog : Animal
{
    public Dog(string name) : base(name) {}

    // 반드시 구현
    public override void MakeSound()
    {
        Console.WriteLine($"{Name}이(가) 멍멍!");
    }
}

class Cat : Animal
{
    public Cat(string name) : base(name) {}

    public override void MakeSound()
    {
        Console.WriteLine($"{Name}이(가) 야옹!");
    }
}


static void Main(string[] args)
{
    Animal dog = new Dog("초코");
    dog.Sleep();
    dog.MakeSound();

    Animal cat = new Cat("나비");
    cat.Sleep();
    cat.MakeSound();
}

실행 예시

초코이() 잠을 잡니다.
초코이() 멍멍!
나비이() 잠을 잡니다.
나비이() 야옹!

요약

항목설명
목적공통 로직 제공 + 자식이 핵심 구현
생성 가능 여부❌ 직접 객체 생성 불가
추상 메서드자식 클래스에서 반드시 override
일반 메서드가능
인터페이스와 차이필드/생성자/기본 구현 가능

주요 키워드 및 개념 설명

키워드개념 설명
:상속을 나타냄 (class Child : Parent)
base부모 클래스의 생성자나 메서드를 호출할 때 사용
virtual부모 클래스에서 메서드 오버라이딩을 허용함
override자식 클래스에서 부모의 virtual 메서드를 재정의할 때 사용
sealed이 클래스를 더 이상 상속할 수 없도록 제한
abstract추상 클래스/메서드 정의 (구현 없이 선언만 가능)
new부모 클래스의 동일한 이름의 멤버를 숨기고 새로 정의할 때 사용

상속 구현

class Unit
{
    public readonly string Name = "None";
    
    public Unit(string name)
	{
    	Name = name;
    }
}

class Character : Unit // 단일 상속
{
	public Character(string name) : base(name) {} // 이런 식으로 부모(Unit)의 생성자 호출

    public virtual void Attack()
    {
        Console.WriteLine($"{Name}이(가) 기본 공격!");
    }
}

// class Warrior : Character, Unit // 이렇게 작성시 Error
sealed class Warrior : Character // 단일 상속, sealed로 더 이상 상속 안함을 명시
{
	public Warrior(string name) : base(name) {} // 이런 식으로 부모(Character)의 생성자 호출
	
    // 가상으로 만들어져 있던 함수를, 오버라이드 해서 재정의하여 사용.
    public override void Attack()
    {
        Console.WriteLine($"{Name}이(가) 검으로 공격!");
    }
}





📦 C#의 class vs struct 차이점

C#에서 classstruct는 객체를 정의할 수 있는 두 가지 방법이다. 이 둘은 사용하는 방식이 유사하지만, 메모리 처리 방식과 구조적으로 몇 가지 중요한 차이점이 있다.

📊 차이점 비교 표

구분classstruct
메모리 위치힙(Heap)스택(Stack)
타입참조 타입 (Reference Type)값 타입 (Value Type)
기본 생성자제공됨 (사용 가능)제공되지만 사용 불가 (사용자 정의만 가능)
상속 가능 여부O (다형성 구현 가능)X (인터페이스 구현만 가능)
null 허용 여부가능불가능 (nullable로 가능: int?)
GC(가비지 컬렉터)대상이 됨대상이 아님
값 복사 방식참조 전달 (주소 복사)값 복사 (전체 복사)
용도복잡하고 크기가 큰 객체에 적합작고, 변하지 않는 데이터에 적합
기본 생성자 호출가능컴파일러가 기본 생성자 자동 생성

감각적으로 사용 해야된다.

  • 게임 캐릭터나 아이템, NPC 같이 많은 데이터와 복잡한 동작들은 class

  • 상속, 추상화, 다형성 필요는 무조건 class

  • 단순한 좌표, 크기, RGB(색상) 등 간단하고 빠르게 처리가 필요한 것들 struct

  • 성능 최적화가 중요할 때(단, 너무 큰 구조체는 오히려 성능 저하가 발생) struct

profile
지모창말, 미모창.

0개의 댓글