C# - 클래스와 객체 (feat.구조체)

MothorMoth·2024년 4월 26일

C#

목록 보기
9/17
post-thumbnail

객체 지향 프로그래밍

  • 객체 지향 프로그래밍(Object-Oriented Programming, OOP)은 데이터와 기능을 객체라는 단위로 캡슐화하여, 상속, 다형성, 캡슐화의 원리를 사용하여 소프트웨어를 모듈화하고 재사용 가능하게 설계하는 프로그래밍 패러다임이다.

객체 지향 프로그래밍의 특징

1. 캡슐화 (Encapsulation)

  • 캡슐화는 데이터(속성)와 그 데이터를 처리하는 메서드를 하나의 클래스 단위로 결합하는 것을 의미한다.

  • 데이터의 세부 구현을 숨기고, 클래스의 공개 인터페이스만을 통해 데이터에 접근할 수 있게 함으로써 프로그램의 안정성과 유지 보수성을 향상시킨다.

2. 상속 (Inheritance)

  • 상속은 한 클래스(부모 클래스, 상위 클래스)가 자신의 속성과 메서드를 다른 클래스(자식 클래스, 하위 클래스)에게 전달하는 메커니즘이다.

  • 코드의 중복을 줄이고, 클래스 간 계층 구조를 구성하여 코드의 구조화와 유지보수를 용이하게 한다.

3. 다형성 (Polymorphism)

  • 다형성은 동일한 인터페이스 또는 메서드 호출이 다양한 형태의 객체에 대해 다른 동작을 할 수 있게 하는 프로그래밍 기능이다.

  • 메서드 오버로딩(동일한 메서드 이름이지만 서로 다른 매개변수를 가짐)과 메서드 오버라이딩(파생 클래스에서 베이스 클래스의 메서드를 재정의)을 통해 구현된다.

4. 추상화 (Abstraction)

  • 추상화는 복잡한 시스템이나 개념을 단순화하여 필요한 기능에 집중하는 것을 의미한다.

  • 클래스와 인터페이스를 통해 구현되며, 주로 필요한 속성과 동작만을 갖는 형태로 실제 세계의 개체를 모델링하여, 프로그램 내에서 필수적인 부분에만 집중할 수 있게 한다.

5. 객체 (Object)

  • 객체는 클래스로부터 생성된 실체로, 클래스에 정의된 속성(데이터)과 동작(메서드)을 가진다.

  • 각 객체는 독립적인 상태와 행동을 가지고 있으며, 다른 객체와 상호 작용하면서 프로그램의 기능을 수행한다.

클래스의 구성 요소

1. 필드 (Fields)

  • 클래스의 멤버 변수로 선언되며, 객체의 특징이나 속성을 표현하고 객체의 데이터를 저장한다.

  • 보통 private 접근 제한자를 사용하여 클래스 외부에서 직접적인 접근을 제한하고, 필요한 경우 프로퍼티를 통해 간접적으로 접근하도록 한다.

class Player
{
    // 필드
    private string name;
    private int level;
}

접근 제한자

  • 접근 제한자(Access Modifier)는 클래스, 필드, 메서드 등의 접근 가능한 범위를 지정하는 키워드.
class Person
{
    public string Name;         // 외부에서 자유롭게 접근 가능
    private int Age;              // 같은 클래스 내부에서만 접근 가능
    protected string Address; // 같은 클래스 내부와 상속받은 클래스에서만 접근 가능
}

프로퍼티

  • 프로퍼티는 클래스 멤버로서, 객체의 필드 값을 간접적으로 읽거나 설정할 수 있게 하는 접근자 메서드의 조합으로, 필드에 대한 접근 제어 및 데이터 유효성 검사를 수행하면서 추가 로직을 통한 상태 관리를 가능하게 한다.

  • getset 접근자를 사용하여 값을 읽거나 설정하는 동작을 정의한다.

  • get 접근자는 프로퍼티의 값을 반환하고, set 접근자는 프로퍼티의 값을 설정한다.
    필요에 따라 get 또는 set 접근자 중 하나를 생략하여 읽기 전용 또는 쓰기 전용 프로퍼티를 정의할 수 있다.

[접근 제한자] [데이터 타입] 프로퍼티명
{
    get
    {
        // 필드를 반환하거나 다른 로직 수행
    }
    set
    {
        // 필드에 값을 설정하거나 다른 로직 수행
    }
}

class Person
{
    private string name;
    private int age;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public int Age
    {
        get { return age; }
        set { age = value; }
    }
}

// 객체 생성 및 프로퍼티 값 설정
Person person = new Person();
person.Name = "John";
person.Age = 25;

Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");

// 프로퍼티 접근 제한자 적용
public string Name
    {
        get { return name; }
        private set { name = value; }
    }

//유효성 검사
public int Age
    {
        get { return age; }
        set
        {
            if (value >= 0)
                age = value;
        }
    }

Person person = new Person();
person.Name = "John";   // 컴파일 오류: Name 프로퍼티의 set 접근자는 private
person.Age = -10;         // 유효성 검사에 의해 나이 값이 설정되지 않는다.
  • 자동 프로퍼티 (Auto Property)는 프로퍼티를 간단하게 정의하고 사용할 수 있는 편리한 기능.
[접근 제한자] [데이터 타입] 프로퍼티명 { get; set; }

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

2. 메서드 (Methods)

  • 클래스의 멤버 함수로 선언되며, 객체의 기능이나 동작을 구현하기 위해 사용되며, 입력값을 받아서 처리한 후 결괏값을 반환, 다른 메서드를 호출하여 작업, 객체의 상태 변경 등을 수행한다.

  • 보통 public 접근 제한자를 사용하여 클래스 외부에서 호출할 수 있도록 한다.

class Player
{
    private string name;
    private int level;

    // 메서드
    public void Attack()
    {
        // 공격 동작 구현
    }
}
  • 메서드를 호출하려면 먼저 해당 메서드가 속해 있는 클래스의 인스턴스를 생성하고, 해당 인스턴스를 통해 메서드를 호출할 수 있다.
// Player 클래스의 인스턴스 생성
Player player = new Player();

// Attack 메서드 호출
player.Attack();

3. 생성자 (Constructor)

  • 객체가 생성될 때 호출되는 특별한 메서드로서 클래스의 인스턴스(객체)를 초기화하고, 필요한 초깃값을을 설정하는 역할을 수행한다.

  • 객체를 생성할 때 new 키워드와 함께 호출되고, 클래스와 동일한 이름을 가지며, 반환 타입이 없다.

  • 매개변수의 유무나 타입, 개수에 따라 다르게 객체를 초기화할 수 있는 생성자를 여러 개 정의할 수 있으며, 이를 생성자 오버로딩(Overloading)이라고 한다.

  • 기본적으로 매개변수가 없는 디폴트 생성자가 자동으로 클래스에 생성되지만, 직접 생성자를 정의할 경우 디폴트 생성자가 자동으로 생성되지 않는다.

class Player
{
    private string name;
    private int level;

    // 매개변수가 없는 디폴트 생성자
    public Player()
    {
        name = "Unknown";
        level = 0;
    }

    // 매개변수를 받는 생성자
    public Player(string newName, int newLevel)
    {
        name = newName;
        level = newLevel;
    }

    public void PrintInfo()
    {
        Console.WriteLine($"Name: {name}, Level: {level}");
    }
}

// 디폴트 생성자 호출
Player player1 = new Player();

// 매개변수를 받는 생성자 호출
Player player2 = new Player("John", 25);

4. 소멸자 (Destructor)

  • 객체가 소멸되는 시점에서 자동으로 호출되는 특별한 메서드로서 객체의 사용이 종료되고 메모리에서 해제될 때 자동으로 호출되어 필요한 정리 작업을 수행한다.

  • 이름 앞에 ~ 기호를 붙여 표현하고, 클래스와 동일한 이름을 가지며, 반환 타입이 없고, 매개변수를 가질 수 없다.

  • C#에서는 가비지 컬렉터(Garbage Collector)가 메모리 해제를 관리하므로, 소멸자를 명시적으로 호출하는 것은 일반적으로 권장되지 않는다.

class Player
{
    private string name;

    public Player(string newName)
    {
        name = newName;
        Console.WriteLine("Player 객체 생성");
    }

    ~Player()
    {
        Console.WriteLine("Player 객체 소멸");
    }
}

구조체

  • 구조체는 struct 키워드를 사용해 선언되며, 변수와 메서드를 포함한 값 형식으로 여러 개의 데이터를 묶어 하나의 사용자 정의 형식을 구성한다.

1. 구조체의 선언

struct Person
{
    public string Name;
    public int Age;

    public void PrintInfo()
    {
        Console.WriteLine($"Name: {Name}, Age: {Age}");
    }
}

2. 구조체의 사용

  • 선언한 구조체의 타입을 가지는 변수를 선언하여 사용할 수 있고, 구조체의 멤버에는 접근할 때 '.' 연산자를 사용한다.
Person person;
person.Name = "John";
person.Age = 25;
person.PrintInfo();

// 출력
// Name: John, Age: 25

3. 구조체 vs 클래스

  • 구조체

    • 구조체는 값 형식이며, 스택에 할당되고 복사할 때 값이 복사된다.
  • 클래스

    • 클래스는 참조 형식이며, 힙에 할당되고 참조로 전달된다.
    • 구조체는 상속을 받을 수 없지만, 클래스는 단일, 다중 상속이 가능하다.
  • 구조체는 작은 크기의 데이터 저장이나 단순한 데이터 구조에 적합하며, 클래스는 더 복잡한 객체를 표현하고 다양한 기능을 제공하기 위해 사용된다.

0개의 댓글