반응형
Event(이벤트)
[delegate의 한계]
delegate int OnClicked();
static void ButtonPressed(OnClicked clickedFunction)
{
clickedFunction();
}
static void Main(string[] args)
{
OnClicked clicked = new OnClicked(Test);
clicked += Test2; // chaining
clicked();
ButtonPressed(clicked);
clicked();
}
델리게이트 형식 OnClicked를 오직 ButtonPressed 함수 안에서만 실행시키기 위해 clickedFunction(); 만들었을 수도 있다. 그러나 상관 없는, 그리고 외부 메인 함수 안에서도 개나소나 델리게이트를 실행시킬 수 있다는 문제가 있다.
[Event]
event는 delegate와 달리 이벤트와 같은 클래스 안에서만 이벤트 호출이 가능하다. 외부에선 오직 이벤트에 함수 등록만 해놓을 수 있으며 이벤트가 정의된 클래스 외부에서는 이벤트를 호출할 수는 없다. 이것이 델리게이트와의 차이점!
InputManager (같은 클래스)
👉 키보드 마우스 입력을 캐치해서 게임 로직에 이를 전달하는 역할로 정의한 클래스다.
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharp
{
class InputManager
{
public delegate void OnInputKey();
public event OnInputKey InputKey; // public 접근 한정자까지 똑같이 맞춰주어야 함
public void Update()
{
if (Console.KeyAvailable == false)
return;
ConsoleKeyInfo info = Console.ReadKey();
if (info.Key == ConsoleKey.A) // A 키가 눌리면 이벤트 호출
{
InputKey(); // 구독자들에게 메세지 뿌리기 👉 옵저버 패턴
}
}
}
}
// Console.KeyAvailable 👉 Key를 누를 수 있는 상태라면 True 리턴, Key를 사용할 수 없으면 False 리턴.
// Console.ReadKey() 👉 사용자가 입력한 Key를 읽어들여 ConsoleKeyInfo 타입으로 리턴한다.
[이벤트 정의하기]
- 1️⃣ 먼저 delegate 형식부터 정의한다. (이벤트에 등록할 수 있는 함수 형식으로 쓸 것이다.)
public delegate void OnInputKey(); // 매개 변수 없고 리턴 타입 없는 함수만 등록 가능한 형식
- 2️⃣ 위에서 만든 delegate 형식을 가지는(= 타입이 해당 delegate인) 이벤트를 정의한다. 접근 한정자 + event + 델리게이트 이름 + 이벤트 이름
public event OnInputKey InputKey; // 이 이벤트의 타입은 OnInputKey 델리게이트
- 델리게이트와 그 델리게이트를 타입으로 하여 정의한 이벤트는 둘 다 접근 한정자가 동일해야 한다. 둘 다 public으로 동일하여 문제 없음.
사용자가 입력한 Key가 A라면 이벤트를 호출(실행)한다. 같은 클래스 내부에서 실행시키는 것이기 때문에 문제 없다.
- InputManager 클래스 외부의 이곳 저곳에서 이 이벤트에 함수를 등록하고 이 이벤트에 등록된 함수가 무엇인지 알 필요 없이 그저 InputManager 클래스내에서 이를 실행만 하면 될 뿐이다.
- 이와 같이 구독자(등록된 함수들)들에게 메세지를 뿌리는 디자인 패턴을 옵저버 패턴이라고 한다.
- 옵저버 패턴은 정보처리기사 디자인 패턴에서도 나왔던 개념이다. 디자인 패턴은 아주 중요하다. 😎
if (info.Key == ConsoleKey.A)
{
InputKey(); // 구독자들에게 메세지 뿌리기 👉 옵저버 패턴
}
Program (외부. 메인 함수 있음)
using System;
using System.Collections.Generic;
namespace CSharp
{
class Program
{
static void OnInputTest()
{
Console.WriteLine("Input Received!");
}
static void Main(string[] args)
{
InputManager inputManager = new InputManager();
inputManager.InputKey += OnInputTest;
while (true)
{
inputManager.Update();
}
// inputManager.InputKey(); 컴파일 에러! 외부에서 호출 불가능
}
}
}
- 이벤트를 사용하기 위해 📜InputManager 타입의 객체를 만들어 inputManager에서 이를 참조한다.
- 이벤트에 OnInputTest() 함수를 등록한다.
inputManager.InputKey += OnInputTest;
- 여기는 📜InputManager 클래스의 외부라서 이벤트를 직접 호출하는 것은 불가능하므로(inputManager.InputKey();는 컴파일 에러) 이 이벤트를 호출하는 📜InputManager의 멤버 함수 inputManager.Update();를 실행시키면 된다!
- 직접 이 안에서 입력이 들어오면 실행시킬 함수들을 구구절절 나열하고 직접 호출해줄 필요가 없이 InputManager.Update();만 실행시켜주면 땡이다!
결론! 델리게이트와 이벤트는 기능은 동일하나 차이점은 👉 델리게이트와 달리 이벤트는 클래스 외부에서는 이벤트를 호출할 수는 없다는 것이다.
반응형
'공부 > 인프런 - Rookiss' 카테고리의 다른 글
Part 1-7-7. 기타 문법 : Exception(예외 처리) (0) | 2023.08.03 |
---|---|
★ Part 1-7-6. 기타 문법 : Lambda(람다식) + Func, Action (0) | 2023.08.03 |
Part 1-7-4. 기타 문법 : Delegate(대리자) (0) | 2023.08.03 |
Part 1-7-3. 기타 문법 : Property(프로퍼티) (0) | 2023.08.03 |
Part 1-7-2. 기타 문법 : Interface(인터페이스) + 다중 상속 (0) | 2023.08.03 |