[C# – 기초 강좌] 5. 클래스(Class) – 객체 지향 프로그래밍(OOP)

객체 지향 프로그래밍(OOP)은 모든 소프트웨어 개발자가 이해해야 할 필수적인 개념 중 하나입니다.

C#은 이러한 원리를 학습하고 구현하기에 탁월한 플랫폼을 제공합니다.

이번 포스팅에서는 C#에서의 클래스(Class), 객체(Object), 속성(Property), 메서드(Method), 상속(Inheritance), 캡슐화(Encapsulation), 다형성 등의 객체 지향 프로그래밍의 핵심 개념들을 배워보도록 하겠습니다.

객체 지향 프로그래밍 (Object-oriented programming, OOP)

객체(Obejct) 란?

프로그래밍에서 객체(Object)는 내 프로그램 내에서 사물이나 개념을 모델링한 것입니다.

객체는 소프트웨어 내에서 자신만의 데이터(속성)와 그 데이터를 처리하는 기능(메서드)을 갖습니다.

객체는 클래스라는 설계도를 바탕으로 생성되며, 클래스는 해당 객체의 모든 가능한 행동과 특성을 정의합니다.

예를 들어, ‘자동차’라는 클래스가 있다면, 이 클래스는 색깔, 모델, 속도와 같은 속성과, 가속하기, 정지하기, 속도 변경하기 등의 메서드를 정의할 수 있습니다.

실제 프로그램에서 ‘자동차’ 클래스의 인스턴스(실체)는 특정 자동차를 나타내며, 각 자동차 객체는 독립적인 속성 값을 가지고 독립적으로 메서드를 실행할 수 있습니다.

class-OOP-object-car-dog-man-tree

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

객체 지향 프로그래밍(Object-Oriented Programming, OOP)은 이러한 객체 개념을 기반으로 한 프로그래밍 패러다임입니다.

OOP에서는 프로그램을 상호작용하는 객체들의 모음으로 보고, 각 객체는 메시지를 주고받으며 데이터를 처리합니다.

이 패러다임의 주요 목표는 실제 세계의 복잡함을 잘 추상화하여 프로그램 내에서 재현하는 것입니다.

특성

  1. 캡슐화(Encapsulation):
    • 객체의 데이터와 메서드를 결합하여 외부에서의 무분별한 접근을 제한합니다.
    • 이로써 데이터 무결성과 보안을 강화할 수 있습니다.
  2. 상속(Inheritance):
    • 코드의 재사용을 극대화하기 위해 한 클래스가 다른 클래스의 특성을 상속받을 수 있습니다.
    • 이를 통해 기능을 확장하고, 기존 코드를 유지하면서 새로운 기능을 추가할 수 있습니다.
  3. 다형성(Polymorphism):
    • 하나의 인터페이스를 통해 다양한 형태로 동작할 수 있는 능력을 말하며, 같은 이름의 메서드가 다양한 방식으로 실행될 수 있습니다.
  4. 추상화(Abstraction):
    • 복잡한 현실 세계의 사물을 단순화시켜 필요한 부분만을 추출하여 프로그램에서 표현합니다.

객체 및 객체지향 프로그래밍과 관련된 글로 다음 글을 참조해주세요.

객체 지향 프로그래밍의 4가지 특징ㅣ추상화, 상속, 다형성, 캡슐화

Class-Characters

클래스(Class)

클래스(Class)란?

클래스는 객체 지향 프로그래밍(OOP)의 핵심 구성 요소 중 하나로, 관련된 속성과 메서드를 그룹화하여 하나의 단위로 묶은 것입니다.

클래스는 실세계의 개체나 개념을 모델링하여 소프트웨어 내에서 표현할 수 있게 해줍니다.

예를 들어, 동물, 차량, 사용자 계정 등 실생활의 다양한 개체들을 클래스를 사용하여 데이터와 기능의 집합으로 표현할 수 있습니다.

클래스의 주요 구성 요소

  1. 필드(Field):
    • 클래스 내부에 저장된 데이터를 표현합니다.
    • 이는 클래스의 상태를 나타내는 변수로 생각할 수 있으며, 예를 들어 ‘동물’ 클래스의 경우 이름, 나이, 종류 등의 필드를 포함할 수 있습니다.
  2. 메서드(Method):
    • 클래스가 수행할 수 있는 동작 또는 기능입니다. 메서드를 통해 클래스의 내부 데이터를 조작하거나, 특정 작업을 실행할 수 있습니다.
    • ‘동물’ 클래스에서는 ‘먹기’, ‘달리기’, ‘소리내기’ 등의 메서드를 정의할 수 있습니다.
  3. 생성자(Constructor):
    • 클래스의 인스턴스, 즉 객체가 생성될 때 자동으로 호출되는 메서드입니다.
    • 주로 객체의 초기화에 사용되며, 필요한 데이터를 받아 객체의 상태를 설정할 수 있습니다.
  4. 속성(Property):
    • 클래스 내부의 필드에 접근을 제어하는 메커니즘으로, 데이터를 안전하게 읽고 쓰는 인터페이스를 제공합니다.
    • 외부에서는 속성을 통해 필드의 값에 접근하고 수정하는데, 이 과정에서 추가적인 로직을 적용할 수 있습니다.

기본 구조 예제

다음 기본적인 Class 구조 및 구성요소를 나타냅니다.

다음 예제에서는 Animal 이라는 객체를 정의하고 있습니다.

using System;

namespace ClassOOP
{
    public class Animal
    {
        // 필드 (Field)
        public string Name;
        private int _age;

        // 생성자 (Constructor)
        public Animal(string name, int age)
        {
            Name = name;
            _age = age;
        }

        // 속성 (Property)
        public int Age
        {
            get { return _age; }
            set { _age = value > 0 ? value : 0; } // Age is set to 0 if value is lower than 0
        }

        // 메서드 (Method)
        public void Speak()
        {
            Console.WriteLine("This animal makes a sound.");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // example for basic class usage
            Animal cat = new Animal("Kitty", 3);

            cat.Age = -2; // Age is lower than 0, so it will be set to 0

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

캡슐화(Encapsulation) 예제

Animal 클래스에서 캡슐화는 필드와 속성을 통해 구현됩니다.

_age 필드는 private으로 선언되어 클래스 외부에서 직접 접근할 수 없으며, 대신 Age라는 공개 속성을 통해 안전하게 접근하고 수정할 수 있습니다.

    public class Animal
    {
        private int _age;

        public int Age
        {
            get { return _age; }
            set { _age = value > 0 ? value : 0; } // Age is set to 0 if value is lower than 0
        }
    }

상속(Inheritance) 예제

상속을 사용하여 Animal 클래스를 확장하는 새로운 클래스를 만들 수 있습니다.

예를 들어, Dog 클래스가 Animal 클래스에서 파생될 수 있으며, 추가적인 특성이나 메서드를 포함할 수 있습니다.

public class Dog : Animal
{
    public string Breed;  // Add field

    public Dog(string name, int age, string breed) : base(name, age)
    {
        Breed = breed;
    }

    public override void Speak()
    {
        Console.WriteLine("Woof!");
    }
}

다형성 (Polymorphism)

Animal 클래스에 정의된 Speak 메서드를 각 동물의 종류에 맞게 재정의함으로써 다형성을 구현할 수 있습니다.

Dog 클래스에서는 Speak 메서드를 “Woof!”라고 출력하도록 재정의하여 동일한 메서드 호출이지만 다른 행동을 하도록 합니다.

추상화 (Abstraction)

Animal 클래스는 동물이라는 추상적인 개념을 구현합니다.

이 클래스는 특정 동물의 구체적인 세부 사항을 제공하지 않고, 동물이라는 개념의 기본적인 속성과 동작만을 정의합니다.

이렇게 함으로써 다양한 동물 종류를 쉽게 추가하고 관리할 수 있습니다.

최신 C# 코딩 문법

레코드 타입

C# 9.0에서 도입된 기능으로, 데이터 전달을 목적으로 하는 클래스를 보다 간결하게 선언할 수 있게 해주는 구문입니다.

레코드는 주로 불변성을 가지며, 주로 데이터를 담는 용도로 사용됩니다.

레코드 타입은 클래스와 유사하지만, 구조적으로 값에 의한 비교(equality), 간결한 구문으로 객체 초기화, 불변성, 데이터 모델링에 적합한 몇 가지 추가 기능을 제공합니다.

Equals(), GetHashCode(), ToString() 등의 메서드를 자동으로 생성하여, 클래스보다 훨씬 간결한 코드로 동일한 기능을 수행할 수 있습니다.

    public record AnimalRecord(string Name, int Age)
    {
        public int Age { get; init; } = Age > 0 ? Age : 0;

        public virtual void Speak()
        {
            Console.WriteLine("This animal makes a sound.");
        }
    }

향상된 패턴 매칭

C# 7.0 이후부터 패턴 매칭은 다양한 문맥에서 타입, 값, 구조적 패턴을 확인할 수 있도록 점점 발전해왔습니다.

C# 9.0에서는 패턴 매칭에 is 표현식 개선, switch 표현식과 함께 타입 패턴, 상수 패턴, 위치 패턴 등이 추가되었습니다.

    public class Animal
    {
        // 필드 (Field)
        public string Name;
        private int _age;

        // Pattern matching example
        public void DescribeAnimal(Animal animal)
        {
            if (animal is { Name: "Lion", Age: >= 5 })
            {
                Console.WriteLine("This is an adult lion.");
            }
            else if (animal is { Name: "Lion", Age: < 5 })
            {
                Console.WriteLine("This is a young lion.");
            }
            else
            {
                Console.WriteLine("This is not a lion.");
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("\r\n## Pattern matching example ##");
            Animal oldLion = new Animal("Lion", 10);
            Animal youngLion = new Animal("Lion", 3);
            Animal elephant = new Animal("Elephant", 15);

            oldLion.DescribeAnimal(oldLion);
            youngLion.DescribeAnimal(youngLion);
            elephant.DescribeAnimal(elephant);
        }
    }

Null 체크 간소화

C# 8.0에서 도입된 null 병합 연산자 (??) 및 null 병합 할당 연산자 (??=)는 null 값을 처리하는 과정을 간소화합니다.

이 연산자들은 null 가능성이 있는 객체를 처리할 때 유용하며, 코드를 더 간결하고 읽기 쉽게 만들어 줍니다.

    // null coalescing assignment example
    public class Zoo
    {
        private Animal _defaultAnimal = new Animal("Elephant", 10);

        public void ShowAnimal(Animal animal)
        {
            // Null 병합 연산자를 사용하여 null 체크
            animal ??= _defaultAnimal;
            Console.WriteLine($"This is a {animal.Name}, and it is {animal.Age} years old.");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // example for null coalescing assignment
            Console.WriteLine("\r\n## Null coalescing assignment example ##");
            Zoo zoo = new Zoo();
            zoo.ShowAnimal(null);
        }
    }

참고 링크

Leave a Comment

Discover more from Devitworld

Subscribe now to keep reading and get access to the full archive.

Continue reading