클래스는 C#에서 가장 핵심적인 타입 중 하나입니다. 클래스를 문제 영역(problem domain)과 관련된 객체를 만들기 위한 설계도(blueprint)라고 생각할 수 있습니다. 즉, 클래스는 객체를 생성하는 템플릿으로, 해당 클래스로부터 만들어지는 모든 객체들이 공유하게 될 구조와 동작을 정의합니다. 쉽게 비유하자면, 클래스는 과자 틀이고 객체는 그 틀로 찍어낸 과자입니다.
클래스는 객체 지향 프로그래밍(OOP)의 중요한 개념인 캡슐화(encapsulation)도 가능하게 해줍니다. 캡슐화란 데이터와 그 데이터를 다루는 연산을 하나의 단위로 묶고, 해당 객체를 사용하는 사람에게 간단한 API만 제공하는 것을 의미합니다. 클래스를 활용하면 데이터를 캡슐화하여 불필요한 세부 사항을 다른 클래스로부터 숨길 수 있습니다.
클래스 선언 방법
클래스는 class 키워드 뒤에 클래스 이름을 붙여서 선언합니다.
// User.cs
public class User{
private string name;
private int salary;
public void Promote(){
salary += 1000;
}
}위 예제에서 User는 사용자를 나타내는 클래스입니다. 이 클래스는 name(이름)과 salary(급여)라는 두 개의 데이터를 캡슐화하고 있으며, 이러한 변수들을 클래스 필드(class field)라고 부릅니다. 또한 사용자의 급여를 인상하는 Promote() 메서드도 포함하고 있습니다.
접근 한정자(Access Modifier)
모든 클래스에는 해당 클래스가 다른 클래스에 얼마나 노출될지를 제어하는 접근 한정자가 지정됩니다. 접근 한정자로 지정할 수 있는 다섯 가지 값은 다음과 같습니다.
| 접근 한정자 | 설명 |
|---|---|
| public | 접근 제한 없음 |
| protected | 파생 클래스(자식 클래스)로만 접근 가능 |
| internal | 동일 어셈블리 내에서만 접근 가능 |
| protected internal | 동일 어셈블리 또는 파생 클래스로만 접근 가능 |
| private | 외부 접근 불가 |
객체 인스턴스 생성하기
클래스의 인스턴스를 생성하려면 new 키워드를 사용합니다. new 연산자는 객체의 데이터를 저장하는 데 필요한 바이트 수를 계산하여 메모리를 할당한 후, 새로 생성된 객체에 대한 포인터(참조라고도 함)를 반환합니다.
var alice = new User(); var bob = new User();
반환된 참조는 = 기호 왼쪽의 변수에 저장됩니다. 위 예제에서 alice와 bob은 각각 새로 생성된 객체에 대한 참조(포인터)를 담고 있습니다.
C#에서 클래스 이름은 각 단어의 첫 글자를 대문자로 표기하는 PascalCase 명명 규칙을 따르는 것이 일반적입니다. 예를 들어 StringBuilder, UserController 등이 있습니다. 클래스 이름과 동일한 파일명을 반드시 사용해야 하는 것은 아니지만, 대부분의 C# 프로젝트에서 관례적으로 사용되는 규칙입니다.
생성자(Constructor)
앞선 예제에서 User 클래스의 인스턴스인 alice와 bob을 생성할 때 초기 이름과 급여를 전달하지 않았습니다. 하지만 새로 생성된 객체가 제 역할을 하려면 보통 몇 가지 정보가 필요하며, 이때 생성자(constructor)를 사용해 클래스 데이터를 초기화합니다.
다음과 같이 생성자를 추가하면 사용자의 이름과 급여를 초기화할 수 있습니다.
public class User{
private string name;
private int salary;
public User(string name, int salary){
this.name = name;
this.salary = salary;
}
public void Promote(){
salary += 1000;
}
}생성자가 있으면 새 인스턴스를 생성할 때 사용자의 이름과 급여를 함께 전달할 수 있습니다.
var alice = new User("Alice", 50000);
var bob = new User("Bob", 45000);하나의 클래스에는 여러 개의 생성자를 정의할 수도 있습니다. 생성자를 여러 개 두면 다양한 방식으로 객체를 초기화할 수 있습니다. 예를 들어, 이름만 받고 급여는 기본값으로 설정하는 생성자를 추가할 수 있습니다.
public User(string name){
this.name = name;
this.salary = 50000;
}전체 예제
using System;
class Program{
static void Main(){
var alice = new User();
alice.Print();
var bob = new User();
bob.Print();
var chris = new User("Chris", 50000);
chris.Print();
var debs = new User("Debs", 45000);
debs.Print();
var scott = new User("Scott");
scott.Print();
}
}
public class User{
private string name;
private int salary;
public User(){
}
public User(string name){
this.name = name;
this.salary = 50000;
}
public User(string name, int salary){
this.name = name;
this.salary = salary;
}
public void Promote(){
salary += 1000;
}
public void Print(){
Console.WriteLine($"{name}: {salary}");
}
}실행 결과
: 0 : 0 Chris: 50000 Debs: 45000 Scott: 50000