추상적인 동작만 정의하고, 구현을 갖지 않는다.
얘는 클래스가 아니다.
다중 상속 가능하며, 여러 클래스가 동일한 인터페이스를 구현할 수 있다.
특정한 기능들에 대한 호환성을 높이고 싶다면 인터페이스 사용.
구조를 만들다보면 "어 이렇게 공통되었는데 얘네들이 다 따로 동작하네? 얘를 인터페이스로 해볼까?"라는 생각이 들 수 있게 차근차근 학습해 나가기
일부 동작의 구현을 가지며, 추상 메서드를 포함할 수 있습니다.(일부 메소드는 구현할 수 있다.)
추상메소드를 포함하고 있는 것이 추상클래스일 뿐 "아예 구현하지 못한다"가 아니다.
얘는 클래스이다.
단일 상속만 가능하며, 다른 클래스와 함께 상속 계층 구조를 형성할 수 있다.
상속을 받아서 뭔가 동작을 해야 된다고 하면 추상클래스가 조금 더 선호될 것.
일련의 연관된 상수들을 명명할 수 있어서 코드의 가독성이 향상되고, 상수를 사용할 때 실수로 잘못된 값을 할당하는 것을 방지할 수 있음.
의미 있는 이름을 사용하여 상수를 명명할 수 있음. 이를 통해 코드의 가독성이 향상되며, 상수의 의미를 명확하게 설명할 수 있음.
스위치 문과 함께 사용될 때 유용함. 열거형을 사용하면 스위치 문에서 다양한 상수 값에 대한 분기를 쉽게 작성할 수 있음.
switch와 쓸 때 호환성이 굉장히 좋다. 가장 깔끔하게 동작~
서로 관련된 상수들의 집합을 정의할 때 사용
각 상수는 정수값으로 지정됨 (실수형은 할 수 없음)
//열거형 정의
enum MyEnum
{
//각각의 명칭들
Value1, //기본값 0
Value2, //1
Value3 //2
}
//열거형 사용
MyEnum myEnum = MyEnum.Value1;
//열거형 상수값 지정
enum MyEnum
{
Value1 = 10,
Value2, //바로 앞에 있는 숫자+1 = 11
Value3 = 20
}
//열거형 형변환
int intValue = (int)MyEnum.Value1; //열거형 값을 정수로 변환
MyEnum enumValue = (MyEnum)intValue; //정수를 열거형으로 변환
enum DaysOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
class Program
{
static void Main(string[] args)
{
DaysOfWeek day = DaysOfWeek.Monday;
Console.WriteLine("Today is " + day); //Today is Monday
}
}
"가독성이 좋아진다"를 알 수 있는 예제
static void Main(string[] args)
{
int userInput = 7;
ProcessMonth(userInput);
}
public enum Month
{
Jan =1,
Feb,
Mar,
Apr,
May,
Jun,
Jul,
Aug,
Sep,
Oct,
Nov,
Dec
}
//public enum Month를 사용하는 함수
public static void ProcessMonth(int month) //main에서 쓸 것이기 때문에 static 붙여주기
{
if (month >= (int)Month.Jan && month <= (int)Month.Dec)
{
Month selectMonth = (Month)month; //받아온 month를 enum형으로 변환
Console.WriteLine("선택한 월은 {0}입니다.", selectMonth);
}
else
{
Console.WriteLine("올바른 월을 입력해 주세요.");
}
}
// 게임 상태
enum GameState
{
MainMenu,
Playing,
Paused,
GameOver
}
// 방향
enum Direction
{
Up,
Down,
Left,
Right
}
// 아이템 등급
enum ItemRarity
{
Common,
Uncommon,
Rare,
Epic
}
예기치 않은 상황(오류가 날 수 있는 상황)
try-catch문 사용하여 예외 처리 수행
try : 예외가 발생할 수 있는 코드 작성
catch : 예외 처리, 예외가 발생했을 때 들어오게 되는 구문
try
{
// 예외가 발생할 수 있는 코드
}
catch (ExceptionType1 ex)
{
// ExceptionType1에 해당하는 예외 처리
}
catch (ExceptionType2 ex)
{
// ExceptionType2에 해당하는 예외 처리
}
finally
{
// 예외 발생 여부와 상관없이 항상 실행되는 코드
//finally는 생략 가능
}
사용자가 원하는 예외 처리를 만들고 싶을 때 사용자 정의 예외 처리를 한다.
필요에 따라 자신만의 예외 클래스를 작성할 수 있다.
Exception 클래스를 상속받아 작성하며, 추가적인 기능이나 정보를 제공할 수 있다.
try-catch문 사용
catch 에서 사용자 정의 예외 타입을 명시하여 예외를 처리하고, 예외에 대한 적절한 처리 로직을 작성한다.
try
{
int result = 10 / 0; // ArithmeticException 발생
Console.WriteLine("결과: " + result);
}
catch (DivideByZeroException ex)
{
Console.WriteLine("0으로 나눌 수 없습니다.");
}
catch (Exception ex)
{
Console.WriteLine("예외가 발생했습니다: " + ex.Message);
}
finally
{
Console.WriteLine("finally 블록이 실행되었습니다.");
}
//Exception 상속받음
public class NegativeNumberException : Exception
{
//string 메세지를 받는 생성자 initializer
public NegativeNumberException(string message) : base(message)
{
}
}
try
{
int number = -10;
if (number < 0)
{
throw new NegativeNumberException("음수는 처리할 수 없습니다.");
}
}
catch (NegativeNumberException ex)
{
Console.WriteLine(ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("예외가 발생했습니다: " + ex.Message);
}
이니셜라이저(initializer)
생성자가 실행되기 전에 처리할 것들을 명시해줌
Exception에 생성자를 먼저 실행하고 옴
NegativeNumberException 실행 → base(message) - 부모의 생성자를 먼저 메세지를 전달해서 동작 → NegativeNumberException 생성자 동작(내용 없음) → Exception에 있는 생성자만 실행
throw
일부러 코드 에러를 발생시킬 때 사용
// 플레이어 이동
try
{
// 플레이어 이동 코드
if (IsPlayerCollidingWithWall())
{
throw new CollisionException("플레이어가 벽에 충돌했습니다!");
}
}
catch (CollisionException ex)
{
// 충돌 예외 처리
Debug.Log(ex.Message);
// 예외에 대한 추가 처리
}
// 리소스 로딩
try
{
// 리소스 로딩 코드
LoadResource("image.png");
}
catch (ResourceNotFoundException ex)
{
// 리소스가 없는 경우 예외 처리
Debug.Log(ex.Message);
// 예외에 대한 추가 처리
}
catch (ResourceLoadException ex)
{
// 리소스 로딩 중 오류가 발생한 경우 예외 처리
Debug.Log(ex.Message);
// 예외에 대한 추가 처리
}
// 게임 상태 전이
try
{
// 상태 전이 코드
if (currentGameState != GameState.Playing)
{
throw new InvalidStateException("게임이 실행 중이 아닙니다!");
}
// 게임 상태 전이 실행
}
catch (InvalidStateException ex)
{
// 상태 예외 처리
Debug.Log(ex.Message);
// 예외에 대한 추가 처리
}
대표적으로 구조체(struct), 일반적인 변수들(기본 데이터 타입들)이 있다.
값형은 변수에 값을 직접 저장한다.
어딘가에 할당을 하거나 대입을 해야 될 때 값을 복사해서 준다.
대표적으로 클래스, 배열, 인터페이스가 있다.
참조형은 변수가 데이터에 대한 참조(메모리 주소)를 저장한다.
변수가 실제 데이터를 가리키는 참조를 갖고 있으며, 해당 변수를 다른 변수에 할당하거나 전달할 때는 참조가 복사된다.
참조형 변수의 수정은 동일한 데이터를 가리키고 있는 다른 변수에 영향을 줄 수 있다.