C# 클래스 마스터하기: 객체 지향 프로그래밍의 청사진
클래스(Class)를 정의하면 데이터 타입에 대한 청사진(Blueprint)을 정의하는 것입니다. 실제 데이터를 정의하는 것은 아니지만, 클래스 이름이 의미하는 바, 즉 클래스 객체가 무엇으로 구성되고 어떤 연산을 수행할 수 있는지를 정의합니다. 객체는 클래스의 인스턴스(Instance)입니다. 클래스를 구성하는 메서드와 변수를 클래스의 멤버(Members)라고 합니다.
클래스 정의
클래스 정의는 class 키워드로 시작하고 클래스 이름이 오며, 중괄호로 클래스 본문을 감쌉니다.
<접근_지정자> class 클래스_이름
{
// 멤버 변수
<접근_지정자> <데이터_타입> 변수1;
<접근_지정자> <데이터_타입> 변수2;
...
// 멤버 메서드
<접근_지정자> <반환_타입> 메서드1(매개변수_리스트)
{
// 메서드 본문
}
...
}
주의사항
- 접근 지정자는 멤버와 클래스 자체의 접근 규칙 지정. 미지정 시 클래스 기본값은
internal, 멤버 기본값은 private
- 데이터 타입은 변수 타입, 반환 타입은 메서드가 반환하는 데이터 타입
- 클래스 멤버 접근은 점(.) 연산자 사용:
객체.멤버
기본 클래스 예제: Box
using System;
namespace BoxApplication
{
class Box
{
public double length; // 길이
public double breadth; // 너비
public double height; // 높이
}
class Boxtester
{
static void Main(string[] args)
{
Box Box1 = new Box();
Box Box2 = new Box();
double volume = 0.0;
// Box1 사양
Box1.height = 5.0;
Box1.length = 6.0;
Box1.breadth = 7.0;
// Box2 사양
Box2.height = 10.0;
Box2.length = 12.0;
Box2.breadth = 13.0;
// 부피 계산
volume = Box1.height * Box1.length * Box1.breadth;
Console.WriteLine("Box1 부피: {0}", volume); // 210
volume = Box2.height * Box2.length * Box2.breadth;
Console.WriteLine("Box2 부피: {0}", volume); // 1560
Console.ReadKey();
}
}
}
멤버 함수와 캡슐화
멤버 함수는 클래스 정의 내에 정의/프로토타입이 있는 함수입니다. 해당 클래스 객체에 대해 동작하며, 그 객체의 모든 멤버에 접근할 수 있습니다.
멤버 변수는 객체의 속성(설계 관점)이며, 캡슐화를 위해 private으로 유지합니다. 이 변수들은 public 멤버 함수를 통해서만 접근 가능하게 합니다.
캡슐화 적용 예제: Set/Get 메서드
using System;
namespace BoxApplication
{
class Box
{
private double length;
private double breadth;
private double height;
public void SetLength(double len) { length = len; }
public void SetBreadth(double bre) { breadth = bre; }
public void SetHeight(double hei) { height = hei; }
public double GetVolume() { return length * breadth * height; }
}
class Boxtester
{
static void Main(string[] args)
{
Box Box1 = new Box();
Box Box2 = new Box();
double volume;
Box1.SetLength(6.0); Box1.SetBreadth(7.0); Box1.SetHeight(5.0);
Box2.SetLength(12.0); Box2.SetBreadth(13.0); Box2.SetHeight(10.0);
volume = Box1.GetVolume();
Console.WriteLine("Box1 부피: {0}", volume); // 210
volume = Box2.GetVolume();
Console.WriteLine("Box2 부피: {0}", volume); // 1560
Console.ReadKey();
}
}
}
C# 생성자 (Constructors)
클래스 생성자는 해당 클래스의 새 객체가 생성될 때마다 실행되는 특수 멤버 함수입니다.
- 클래스와 정확히 같은 이름
- 반환 타입 없음 (void도 쓰지 않음)
기본 생성자 예제
using System;
namespace LineApplication
{
class Line
{
private double length;
public Line() // 기본 생성자
{
Console.WriteLine("객체 생성 중");
}
public void SetLength(double len) { length = len; }
public double GetLength() { return length; }
static void Main(string[] args)
{
Line line = new Line(); // 생성자 호출
line.SetLength(6.0);
Console.WriteLine("선 길이: {0}", line.GetLength()); // 6
Console.ReadKey();
}
}
}
매개변수 있는 생성자 (Parameterized Constructor)
public Line(double len) // 매개변수 있는 생성자
{
Console.WriteLine("객체 생성, 길이 = {0}", len);
length = len;
}
// 사용
Line line = new Line(10.0); // 생성 시 초기값 설정
Console.WriteLine("선 길이: {0}", line.GetLength()); // 10
C# 소멸자 (Destructors)
소멸자는 클래스 객체가 범위를 벗어날 때 실행되는 특수 멤버 함수입니다.
- 클래스 이름 앞에 틸드(
~)를 붙인 이름
- 값을 반환할 수 없음, 매개변수 받을 수 없음
- 상속/오버로드 불가
- 프로그램 종료 전 메모리 리소스 해제에 유용
소멸자 예제
using System;
namespace LineApplication
{
class Line
{
private double length;
public Line() { Console.WriteLine("객체 생성됨"); }
~Line() { Console.WriteLine("객체 삭제됨"); } // 소멸자
public void SetLength(double len) { length = len; }
public double GetLength() { return length; }
static void Main(string[] args)
{
Line line = new Line();
line.SetLength(6.0);
Console.WriteLine("선 길이: {0}", line.GetLength());
} // Main 끝날 때 line 소멸자 호출
}
}
출력: 객체 생성됨 → 선 길이: 6 → 객체 삭제됨
C# 클래스의 정적 멤버 (Static Members)
static 키워드로 클래스 멤버를 정적으로 정의할 수 있습니다. 클래스의 객체가 몇 개 생성되든 정적 멤버는 단 하나만 존재합니다.
- 정적 변수: 상수 정의용으로 사용 (인스턴스 생성 없이 클래스 이름으로 접근 가능)
- 정적 변수는 멤버 함수 외부나 클래스 정의 내부에서 초기화 가능
- 정적 함수: 정적 변수만 접근 가능. 객체 생성 전에도 존재
정적 변수 예제
using System;
namespace StaticVarApplication
{
class StaticVar
{
public static int num = 0;
public void Count() { num++; }
public int GetNum() { return num; }
}
class StaticTester
{
static void Main(string[] args)
{
StaticVar s1 = new StaticVar();
StaticVar s2 = new StaticVar();
s1.Count(); s1.Count(); s1.Count(); // num = 3
s2.Count(); s2.Count(); s2.Count(); // num = 6
Console.WriteLine("s1의 num: {0}", s1.GetNum()); // 6
Console.WriteLine("s2의 num: {0}", s2.GetNum()); // 6 (공유됨)
Console.ReadKey();
}
}
}
정적 함수 예제
class StaticVar
{
public static int num = 0;
public void Count() { num++; }
public static int GetNum() { return num; } // 정적 메서드
}
static void Main()
{
StaticVar s = new StaticVar();
s.Count(); s.Count(); s.Count();
Console.WriteLine("num: {0}", StaticVar.GetNum()); // 클래스 이름으로 호출, 3 출력
}
핵심 정리: 클래스는 참조 타입, 힙 할당, 상속 지원, 소멸자 있음. 구조체는 값 타입, 스택 할당(주로), 상속 불가, 소멸자 없음. 용도에 맞게 선택하세요.