1. 클래스 선언의 기본 구조
자, 상상해봐: C#에서 클래스는 건물 설계도야. 설계도에는 방이 몇 개, 벽 색깔, 문이랑 창문 위치 같은 걸 적지. 클래스에는 객체가 어떤 속성(예: 이름, 나이)을 갖고, 뭘 할 수 있는지(예: "인사하기", "월급 요청하기")를 적는 거야.
클래스 선언에는 항상 세 가지 기본 블록이 있어:
- 접근 제한자 (public, private, internal, protected) — 누가 이 클래스를 쓸 수 있는지 정하는 거야. 지금은 public만 쓸게. 이러면 클래스가 "어디서나 보임".
- class 키워드 — 컴파일러한테 "나 지금 클래스 설명 중이야"라고 알려주는 거지.
- 클래스 이름 — 관례상 첫 글자는 대문자야.
- 중괄호 안에 클래스 본문 — 여기서 필드, 프로퍼티, 메서드 등 클래스의 모든 걸 적어.
도식으로 보면 이렇게 돼:
public class 클래스이름
{
// 여기에 클래스의 필드, 프로퍼티, 메서드가 들어감
}
예시: 학생 클래스
public class Student
{
// 필드 (객체에 속한 변수)
public string Name;
public int Age;
}
아직 이 클래스는 그냥 빈 상자야: 학생은 이름이랑 나이가 있어야 한다고만 적었고, 아직 아무것도 못 해.
2. 클래스 필드 (fields)
필드는 클래스 객체에 속한 변수야. 예를 들어, 학생마다 이름과 나이가 다르니까 필드로 적는 거지:
public class Student
{
public string Name;
public int Age;
}
이제 Student 타입 객체를 만들면, 각각 자기만의 이름과 나이를 갖게 돼.
객체 생성 예시:
Student sasha = new Student();
sasha.Name = "사샤";
sasha.Age = 20;
여기서 sasha라는 객체를 만들고, 필드에 값을 따로 넣어줬어. 이 방식은 완전 기초 시작할 때 많이 써 (생성자 얘기는 다음 강의에서 자세히 할 거야).
3. 클래스 메서드 (functions)
메서드는 객체의 "동사"야, 즉 행동이지. 객체가 할 수 있는 동작들. 예를 들어, 학생이 인사할 수 있어. 그럼 클래스 안에 메서드를 적는 거야:
public class Student
{
public string Name;
public int Age;
public void SayHello()
{
Console.WriteLine($"안녕, 내 이름은 {Name}이고, 나는 {Age}살이야!");
}
}
이제 학생마다 "인사하기"를 할 수 있고, 자기 이름과 나이를 쓸 수 있어.
메서드 사용 예시:
Student sasha = new Student();
sasha.Name = "사샤";
sasha.Age = 20;
sasha.SayHello(); // 출력: 안녕, 내 이름은 사샤이고, 나는 20살이야!
4. 클래스 프로퍼티 (properties)
프로퍼티는 "똑똑한" 필드야. 값을 읽거나 쓸 때 특별한 동작을 넣을 수 있어. 요즘 C#에서는 필드보다 프로퍼티를 더 많이 써, 왜냐면 더 컨트롤하기 쉽고 유연하거든. 전기처럼: 단순해 보여도 쓸 수 있는 게 엄청 많아.
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
여기서 get; set;은 자동으로 필드를 만들어주고, 나중에 값 바꿀 때 로직도 추가할 수 있어. 클래스 쓰는 입장에서는 필드랑 거의 똑같이 보여.
예시:
Student katya = new Student();
katya.Name = "카탸";
katya.Age = 18;
Console.WriteLine(katya.Name); // 카탸
프로퍼티에 대한 자세한 얘기는 다음 강의에서 할게 :P
5. 주석 (comments)
지루하지만 진짜 중요한 얘기! 다른 코드랑 마찬가지로, 클래스 안에도 주석을 꼭 써야 해. 왜 이 필드나 메서드가 필요한지 설명해두면 좋아:
public class Student
{
// 학생 이름
public string Name { get; set; }
// 학생 나이 (나이 단위: 년)
public int Age { get; set; }
// 학생이 인사함
public void SayHello()
{
Console.WriteLine($"안녕, 내 이름은 {Name}이고, 나는 {Age}살이야!");
}
}
이렇게 하면 코드 읽기 편하고, 프로젝트가 커져도 길을 잃지 않아.
6. 접근 제한자
접근 제한자는 거의 자물쇠 달린 문 같아. 누가, 어디서 클래스 멤버에 접근할 수 있는지 정해. 주요 제한자는:
- public: 어디서나 접근 가능 (우리는 기본적으로 이거 씀).
- private: 이 클래스 안에서만 접근 가능.
- internal: 현재 어셈블리(프로젝트, 라이브러리) 안에서만 접근 가능.
- protected: 이 클래스랑 상속받은 클래스에서만 접근 가능.
외부에서 못 보게 필드를 숨기는 예시:
public class Student
{
private int age; // Student 안에서만 사용
public string Name { get; set; }
public void SetAge(int value)
{
if (value > 0)
age = value;
}
public int GetAge()
{
return age;
}
}
처음엔 멤버를 전부 public으로 선언하는 경우가 많은데, 실제 프로젝트에서는 이러면 안 돼. 구현 세부사항은 숨기는 게 좋아.
7. static 멤버
가끔 클래스에 객체 하나하나가 아니라, 전체 클래스에 속하는 데이터나 메서드가 필요할 때가 있어. 이게 바로 static 멤버(static members)야.
예를 들어: 전체 학생 수를 세고 싶을 때.
public class Student
{
public static int StudentsCount = 0;
public string Name { get; set; }
public int Age { get; set; }
}
static 멤버는 클래스 이름으로 접근해:
Student.StudentsCount = 0;
각 객체마다 자기만의 프로퍼티/필드가 있지만, static 멤버는 전부 공유해. 위 예시에서 학생이 10명이어도 Name은 각자 다르고, StudentsCount는 모두가 같이 써.
8. 예시: 완성된 학생 클래스 (메서드 포함 버전)
이제 전부 합쳐서, 제대로 된 학생 클래스를 만들어보자:
public class Student
{
// static 학생 수 카운터 - 모든 학생에 해당
public static int Count = 0;
// 이름과 나이 - 프로퍼티
public string Name { get; set; }
public int Age { get; set; }
// 생성자 (생성자 얘기는 다음 강의에서!)
public Student(string name, int age)
{
Name = name;
Age = age;
Count++; // 객체 만들 때마다 카운터 증가
}
// 인사 메서드
public void SayHello()
{
Console.WriteLine($"안녕! 나는 {Name}야. 나는 {Age}살이야.");
}
}
메인 프로그램에서 사용 예시:
class Program
{
static void Main()
{
Student sasha = new Student("사샤", 20);
Student katya = new Student("카탸", 22);
sasha.SayHello();
katya.SayHello();
Console.WriteLine($"전체 학생 수: {Student.Count}");
}
}
9. 코드 구성: 한 파일 = 한 클래스
.NET에서는 public 클래스마다 파일을 따로 만들어. 파일 이름도 클래스 이름이랑 똑같이 해. 예를 들어:
Student.cs
|
|__ public class Student
그리고 메인 프로그램 파일(Program.cs)에는 진입점이랑 주요 코드를 넣어. 클래스가 많아지면 이렇게 해야 프로젝트 관리가 쉬워져.
10. 클래스와 객체 다룰 때 자주 하는 실수
실수 1: 중괄호를 빼먹거나 잘못 썼을 때.
컴파일러가 바로 에러를 내지만, 어디가 문제인지 잘 안 보일 때도 있어. 특히 코드가 길면 중괄호 위치 찾기 힘들어.
실수 2: 같은 네임스페이스에 이름이 같은 클래스를 두 번 선언함.
이런 "창의성"은 컴파일러가 허락 안 해. 다행이지, 아니면 네가 어떤 클래스를 쓰는지 헷갈릴 거야.
실수 3: 필드랑 프로퍼티 이름을 똑같이 줌.
클래스 멤버 쓸 때 헷갈려. 심지어 경력자도 "이거 필드야, 프로퍼티야?" 하면서 머리 싸매.
실수 4: 접근 제한자를 안 적음.
기본값이 internal이라서, 라이브러리 만들 때 외부에서 클래스에 접근 못 하게 될 수도 있어.
실수 5: static 멤버를 인스턴스로 접근함.
student.Count라고 쓰면 Student.Count 대신에, 컴파일러가 막진 않지만 헷갈려. 마치 Count가 특정 학생한테만 있는 것처럼 보이지만, 사실은 모두에게 해당되는 거야.
GO TO FULL VERSION