다음을 통해 공유


클래스(Visual C# Express)

업데이트: 2007년 11월

C#은 개체 지향 프로그래밍 언어이며 다른 현대적 언어와 마찬가지로 관련 필드, 메서드, 속성 및 이벤트를 클래스라는 데이터 구조로 그룹화합니다.

클래스와 개체 비교

클래스는 기본적으로 사용자 지정 데이터 형식을 위한 청사진 역할을 합니다. 클래스를 정의한 다음에는 이를 메모리에 로드하여 사용합니다. 메모리에 로드된 클래스를 개체 또는 인스턴스라고 합니다. 클래스의 인스턴스를 만들려면 C#의 new 키워드를 사용합니다.

다음 예제에서는 SampleClass라는 클래스를 정의하고 이 클래스의 인스턴스인 sampleClass1이라는 개체를 만듭니다. C#에서는 클래스 내에 Main 함수를 정의해야 하므로, 다음 코드에서는 Program 클래스를 정의하지만 이 클래스는 개체를 만드는 데 사용하지 않습니다.

using System;

class SampleClass
{
    public void SayHello()
    {
        Console.WriteLine("Hello, World!");
    }
}

class Program
{
    //Main is the entrypoint, where every C# program starts
    static void Main(string[] args)
    {
        SampleClass sampleClass1 = new SampleClass();  // Create an object
        sampleClass1.SayHello();                       // Call a method
    }
}

동일한 청사진을 바탕으로 여러 채의 집을 지을 수 있듯이 동일한 클래스의 개체를 원하는 수만큼 인스턴스화할 수 있습니다. 배열 또는 목록에 동일한 클래스의 여러 개체가 포함되는 것은 매우 일반적입니다. 클래스의 각 인스턴스는 별도의 메모리 공간을 차지하며 아래 설명된 정적 필드를 제외한 필드의 값은 개별적이며 독립적입니다. 아래의 예제 코드에서는 크기가 2로 설정되는 Animal 형식의 개체 하나와 크기가 3으로 설정되는 다른 개체를 만들 수 있습니다. 그러나 정적 멤버에는 예외적으로 이 규칙이 적용되지 않습니다.

정적 멤버와 인스턴스 멤버

정적 멤버는 특정 클래스의 인스턴스에 대한 참조 없이 액세스할 수 있는 메서드 또는 필드입니다. 가장 일반적인 정적 메서드는 모든 C# 프로그램의 진입점인 Main입니다. Main 메서드는 이를 포함하는 클래스의 인스턴스를 만들지 않아도 호출할 수 있습니다. 자주 사용되는 다른 정적 메서드로 Console 클래스의 WriteLine이 있습니다. 정적 메서드에 액세스할 때는 다른 구문을 사용합니다. 즉, Console.WriteLine과 같이 점 연산자 왼쪽에 인스턴스 이름 대신 클래스 이름을 사용합니다.

클래스 필드를 static으로 선언하면 해당 클래스의 모든 인스턴스에서 그 필드를 "공유"합니다. 다음 예제 코드에서 size가 static으로 선언되었다면 하나의 Animal 개체에서 값을 변경할 경우 Animal 형식의 모든 개체에서 값이 변경됩니다.

정적 클래스는 모든 멤버가 static인 클래스입니다. 어떤 상황에서는 정적 클래스, 메서드 및 필드를 사용하는 것이 성능 및 효율성 면에서 유용할 수 있습니다. 그러나 정적인 필드를 인스턴스 필드라고 가정하면 사소한 오류가 발생할 수 있습니다. 자세한 내용은 정적 클래스 및 정적 클래스 멤버(C# 프로그래밍 가이드)를 참조하십시오.

클래스와 파일 비교

모든 C# 프로그램에는 하나 이상의 클래스가 있습니다. 프로그램을 디자인할 때 각 소스 코드 파일(.cs)에 하나의 클래스를 유지하는 것이 바람직한 프로그래밍 습관입니다. C# IDE(통합 개발 환경)을 사용하여 클래스를 만들 경우에는 새 소스 코드 파일이 동시에 자동으로 만들어집니다.

캡슐화

클래스는 일반적으로 사물의 특징 및 이 사물에서 수행할 수 있는 작업을 표현합니다. 예를 들어, 동물을 C# 클래스로 표현하려면 크기, 속도 및 힘을 숫자로 나타내고 MoveLeft(), MoveRight(), SpeedUp() 및 Stop() 같은 함수를 정의합니다. 이러한 함수에서는 "동물"이 각각의 동작을 하는 데 필요한 코드를 작성합니다. C#에서 동물 클래스는 다음과 같습니다.

    public class Animal
    {
        private int size;
        private float speed;
        private int strength;

        public void MoveLeft()  // method
        {
            // code goes here...
        }

        // other methods go here...
    }

.NET Framework Class Library를 탐색해 보면 "사물"을 표현하는 XmlDocument, String, Form 같은 클래스를 볼 수 있고, 각 사물에는 수행 가능한 여러 가지 작업(메서드), 읽고 수정할 수 있는 특징(속성) 및 특정 작업을 수행할 때 보내지는 알림(이벤트)이 있음을 알 수 있습니다. 메서드, 속성 및 이벤트와 더불어 기타 모든 내부 변수 및 상수(필드)를 클래스의 멤버라고 합니다.

멤버를 클래스에 그룹화하면 논리적일 뿐만 아니라 원치 않는 다른 코드에서 액세스할 수 없도록 데이터와 함수를 숨길 수 있습니다. 이러한 원리를 캡슐화라고 합니다. .NET Framework 클래스 라이브러리를 탐색할 때는 해당 클래스의 공용 멤버만 볼 수 있습니다. 클래스 자체나 관련 클래스에서 내부적으로만 사용하고 다른 응용 프로그램에 사용되지 않는 전용 멤버가 각 클래스에 있을 수도 있습니다. 사용자 자신의 클래스를 만들 때에는 공용이 될 멤버와 전용이 될 멤버를 결정해야 합니다.

상속

클래스를 다른 클래스에서 상속할 수 있습니다. 즉, 상속된 클래스는 원래 클래스의 모든 멤버(공용 및 전용)를 포함할 뿐 아니라 추가로 멤버를 정의할 수 있습니다. 상속 관계에서 원래의 클래스를 기본 클래스라고 하며 새로운 클래스를 파생 클래스라고 합니다. 기본 클래스에서 변형된 보다 구체적인 특성을 표현하기 위해 파생 클래스를 만듭니다. 예를 들어, Animal에서 상속되는 Cat 클래스를 정의할 수 있습니다. Cat은 Animal에 공통인 모든 동작과 더불어 고양이만의 고유한 동작 하나를 추가로 할 수 있습니다. C# 코드는 다음과 같습니다.

    public class Cat : Animal
    {
        public void Purr()
        {
        }
    }

Cat : Animal이라는 표기법은 Cat이 Animal에서 상속되며 따라서 Cat은 MoveLeft 메서드와 세 개의 전용 변수인 size, speed 및 strength를 가짐을 나타냅니다. Cat에서 상속되는 SiameseCat 클래스를 정의할 경우 이 클래스는 Cat의 모든 멤버와 Animal의 모든 멤버를 갖게 됩니다.

다형성

컴퓨터 프로그래밍 분야에서 다형성이란 기본 클래스에서 파생된 메서드를 파생 클래스에서 다시 정의(재정의)하는 기능을 나타냅니다. 기본 클래스에 정의되지 않은 기능이나 기본 클래스에 정의된 것과는 다른 기능 등, 파생된 메서드에서 고유의 특정 기능이 필요할 때 이와 같이 메서드를 재정의합니다. 예를 들어, Animal.MoveLeft 메서드는 모든 동물에 적용되기 위해 매우 일반적이어야 합니다. 이 메서드는 "동물의 머리가 X 방향을 가리키도록 방향을 변경한다"처럼 매우 단순할 것입니다. 그러나 Cat 클래스의 경우 이것만으로는 부족할 수 있습니다. Cat이 몸을 돌릴 때 발톱과 꼬리가 어떻게 움직이는지 지정해야 할 수도 있습니다. 또한 Fish 클래스나 Bird 클래스를 정의했다면 이러한 각각의 클래스에서 서로 다른 방식으로 MoveLeft 메서드를 재정의해야 할 수도 있습니다. 특정 클래스에 맞도록 MoveLeft 메서드의 동작을 사용자 지정할 수 있으므로, 클래스를 만들고 메서드를 호출하는 코드에 세계의 모든 동물 각각에 대한 별도의 메서드를 포함하지는 않습니다. 개체가 Amimal에서 상속되는 경우 호출하는 코드에서는 단순히 MoveLeft 메서드를 호출하면 되고, 그러면 자동으로 이 개체가 소유한 고유 버전이 호출됩니다.

생성자

모든 클래스에는 생성자, 즉 클래스와 이름이 같은 메서드가 있습니다. 생성자는 클래스 정의를 기반으로 개체가 만들어질 때 호출됩니다. 일반적으로 생성자는 클래스에 정의된 변수의 초기 값을 설정합니다. 필요한 초기 값이 숫자 데이터 형식의 경우 0, 부울 데이터 형식의 경우 false, 참조 형식의 경우 null이면 초기 값을 굳이 설정하지 않아도 됩니다. 이러한 데이터 형식은 자동으로 초기화되기 때문입니다.

원하는 만큼 많은 매개 변수를 사용하여 생성자를 정의할 수 있습니다. 매개 변수가 없는 생성자를 기본 생성자라고 합니다. 다음 예제에서는 문자열을 받는 생성자 및 기본 생성자를 가지는 클래스를 정의한 다음 각 생성자를 사용합니다.

class SampleClass
{
    string greeting;

    public SampleClass()
    {
        greeting = "Hello, World";
    }

    public SampleClass(string message)
    {
        greeting = message;
    }

    public void SayHello()
    {
        System.Console.WriteLine(greeting);
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Use default constructor.
        SampleClass sampleClass1 = new SampleClass();
        sampleClass1.SayHello();

        // Use constructor that takes a string parameter.
        SampleClass sampleClass2 = new SampleClass("Hello, Mars");
        sampleClass2.SayHello();
    }
}

연산자 오버로드

동일한 이름의 다른 메서드(이전 예제의 경우 SampleClass())를 만드는 것을 재정의라고 합니다. 인수가 있는 경우 개체를 만들 때마다 인수의 목록이 제공되므로 컴파일러는 어떤 메서드를 사용해야 하는지 알 수 있습니다. 오버로드하면 코드가 더 융통성 있고 읽기 쉽게 됩니다.

소멸자

C++를 사용해 본 적이 있으면 소멸자에 대해 이미 알고 있을 것입니다. C#에는 자동 가비지 수집 시스템이 있으므로 클래스에서 관리되지 않는 리소스를 사용하지 않는 한 소멸자를 구현할 필요는 없습니다. 자세한 내용은 소멸자(C# 프로그래밍 가이드)를 참조하십시오.

구조체

구조체는 상속을 지원하지 않는다는 점만 제외하고는 여러 면에서 클래스와 유사한 형식입니다. 자세한 내용은 구조체(Visual C# Express)를 참조하십시오.

참고 항목

작업

방법: 개체에 대한 메서드 호출(Visual C#)

방법: 클래스에서 상속(Visual C#)

개념

C# 언어 입문

참조

클래스 및 구조체(C# 프로그래밍 가이드)

class(C# 참조)

struct(C# 참조)