클래스
struct와 class 비교
둘 모두 사용자 정의 자료형을 만들기 위한 녀석들이지만, 분명한 차이가 있으니 사용에 주의해야함
구조체 struct | 클래스 class | |
보관되는 곳 | 스택 영역 | 힙 영역 |
할당 방식 | 값 저장 | 참조 저장 |
복사 방식 | 개별 복사 (복사 값 수정해도 기존 값 영향 X) | 참조 복사 (복사 값 수정 시 기존 값도 변경 O) |
상속 여부 | 불가능 | 가능 |
클래스의 접근 제한자
class Person
{
/* 필드 */
public string Name; // 외부에서 자유롭게 접근 가능
private int Age; // 같은 클래스 내부에서만 접근 가능
protected string Address; // 같은 클래스 내부와 상속받은 클래스에서만 접근 가능
/* 메서드 */
public void Attack()
{
// 공격 동작 구현
}
}
- public은 어디서든 접근 가능, 대개 메서드는 public으로 선언
- private는 소속 클래스 내부에서만 접근 가능, 대개 필드는 private로 선언
- protected는 소속 클래스 및 그 클래스를 상속 받은 클래스에서만 접근 가능
생성자와 소멸자
1) 생성자 Constructor
- 인스턴스를 생성할 때 함께 호출되는 특별한 메서드
- 클래스와 이름이 같아야하고, void 타입이어야 함
- 생성자도 오버로딩을 통해 다양한 매개변수 유형을 처리할 수 있음
class Person
{
/* 필드 */
private string name;
private int age;
/* 매개변수가 없는 생성자 예시 */
public Person()
{
name = "Unknown";
age = 0;
}
/* 매개변수를 받는 생성자 예시 */
public Person(string newName, int newAge)
{
name = newName;
age = newAge;
}
/* 메서드 */
public void PrintInfo()
{
Console.WriteLine($"Name: {name}, Age: {age}");
}
}
/* 인스턴스 생성 */
Person person1 = new Person(); // 디폴트 생성자 호출
Person person2 = new Person("John", 25); // 매개변수를 받는 생성자 호출
2) 소멸자 Destructor
- 인스턴스가 소멸될 때(=메모리에서 해제될 때) 자동으로 호출되는 특별한 메서드
- 클래스와 이름이 같지만, 앞에 ~ 기호를 붙임
- 매개변수를 가질 수 없으며, void 타입이어야 함
class Person
{
private string name;
/* 생성자 */
public Person(string newName)
{
name = newName;
Console.WriteLine("Person 객체 생성");
}
/* 소멸자 */
~Person()
{
Console.WriteLine("Person 객체 소멸");
}
}
프로퍼티
- 클래스의 필드 값을 읽거나 쓸 때 사용되는 접근자(Accesor) 메서드의 조합
- 필드에 직접 접근할 수 없도록 제어할 수 있고, write 되는 데이터에 대한 유효성 검사 등을 수행 가능
- get 접근자는 프로퍼티의 값을 반환하고, set 접근자는 프로퍼티의 값을 설정
- 둘 중 하나만 작성함으로써 읽기 전용 또는 쓰기 전용 프로퍼티화 할 수 있음!!
/* 클래스 */
class Person
{
private string name;
private int age;
// Name 필드는 외부에서 값을 설정할 수 없음
public string Name
{
get { return name; }
private set { name = value; }
}
// Age 필드에 값을 설정할 땐 0보다 큰 정수여야 함
public int Age
{
get { return age; }
set
{
if (value >= 0)
age = value;
}
}
}
/* 인스턴스 */
Person person = new Person();
// set 접근자 실행
person.Name = "John"; // compile error : private 제한자는 외부에서 set할 수 없음
person.Age = -10; // 음수는 set할 수 없음
// get 접근자 실행
Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
상속
기존 클래스를 확장하거나 재사용해 새로운 클래스를 생성하는 것
자식 클래스가 부모 클래스의 멤버들을 상속 후 확장하거나 수정해 활용 (멤버 : 필드, 메서드, 프로퍼티 등)
다형성 Polymorphism
같은 타입이지만 다양한 동작을 수행할 수 있는 능력
자식 클래스마다 재정의됨으로써 결이 같은 메서드여도 클래스에 따라 상이한 로직이 처리되도록 하는 특징
가상 메서드
- 부모 클래스에서 virtual 키워드로 선언된 메서드는 자식 클래스에서 재정의될 수 있음
- 자식 클래스에서 재정의되는 메서드는 override 키워드로 선언
/* 부모 클래스 */
public class Unit
{
public virtual void Move()
{
Console.WriteLine("두발로 걷기");
}
}
/* 자식 01 */
public class Marine : Unit
{
// Unit에게서 Move 상속
}
/* 자식 02 */
public class Zergling : Unit
{
// Unit에게서 Move 상속, 가상 메서드인 Move를 저글링에 맞게 재정의
public override void Move()
{
Console.WriteLine("네발로 걷기");
}
}
추상 클래스와 추상 메서드
- 추상 클래스는 직접 인스턴스를 생성할 수 없는 클래스 (상속 전용)
- 추상 메서드는 추상 클래스에 선언할 수 있으며, 둘다 abstract 키워드를 통해 선언
- 추상 메서드는 구현부가 없기 때문에, 자식 클래스에서 반드시 구현을 마쳐주어야 함
/* 추상 클래스 */
abstract class Shape
{
public abstract void Draw(); // 구현부 {}가 없는 추상 메서드
}
/* 자식 클래스 */
class Circle : Shape
{
public override void Draw() // 자식 클래스에서 상속받아 구현 마침
{
Console.WriteLine("Drawing a circle");
}
}
제너릭 Generic
- 클래스 또는 메서드를 일반화시켜 다양한 자료형에 대응할 수 있도록 하는 기능
- <T> 키워드를 활용해 선언된 클래스나 메서드는 사용 시점에 자료형을 결정 (선언 시점 X)
- 인스턴스를 생성하거나, 메서드를 호출할 때는 자료형을 지정해주어야 함
/* 제너릭 클래스 */
class Stack<T>
{
// elements 배열에 담길 요소들의 자료형 -> 제너릭
private T[] elements;
private int top;
public Stack()
{
elements = new T[100];
top = 0;
}
// Push 매개변수의 자료형 -> 제너릭
public void Push(T item)
{
elements[top++] = item;
}
// Pop 반환값의 자료형 -> 제너릭
public T Pop()
{
return elements[--top];
}
}
/* 제너릭 클래스의 인스턴스를 생성할 땐 자료형을 지정해줘야 함 */
Stack<int> intStack = new Stack<int>(); // <T> -> <int>
intStack.Push(1);
intStack.Push(2);
Console.WriteLine(intStack.Pop()); // 출력 결과: 2
'C# 공부' 카테고리의 다른 글
C# 기본기 05 - 인터페이스와 열거형(Enums) (0) | 2025.02.10 |
---|---|
C# 기본기 03 - 메서드와 구조체 (0) | 2025.02.10 |
C# 기본기 02 - 배열과 콜렉션 (0) | 2025.02.10 |
C# 기본기 01 - 기본 자료형, 형 변환, 문자열 (0) | 2025.02.10 |