→ 봉인 용도
클래스 봉인
using UnityEngine;
public sealed class BaseClass : MonoBehaviour
{
public void Method()
{
Debug.Log("일반 함수");
}
}
// 클래스 봉인으로 상속 불가
public class DerivedClass : BaseClass
{
}
일반적인 함수
using UnityEngine;
public class BaseClass : MonoBehaviour
{
public void Method()
{
Debug.Log("일반 함수");
}
}
가상 함수
using UnityEngine;
public class BaseClass : MonoBehaviour
{
public virtual void Method()
{
Debug.Log("가상 함수");
}
}
public class DerivedClass : BaseClass
{
public override void Method()
{
Debug.Log("오버라이드 함수");
}
}
using UnityEngine;
public class ParentClass : MonoBehaviour
{
public virtual void Method() // 가상 함수
{
Debug.Log("Method");
}
}
public class StudySealed : ParentClass
{
public sealed override void Method() // 오버라이드된 함수
{
base.Method(); // 부모 클래스의 함수 기능을 가져오는 방법
Debug.Log("Override Method");
}
}
public class ChildClass : StudyClass
{
public override void Method()
{
}
}
추상 함수
using UnityEngine;
public abstract class BaseClass : MonoBehaviour
{
public abstract void Method();
}
public class DerivedClass : BaseClass
{
public override void Method()
{
Debug.Log("오버라이드 함수");
}
}
using UnityEngine;
public abstract class ParentClass : MonoBehaviour
{
public abstract void Method(); // 추상 함수
}
public class StudySealed : ParentClass
{
public sealed override void Method() // 오버라이드된 함수
{
Debug.Log("Override Method");
}
}
public class ChildClass : StudyClass
{
public override void Method()
{
}
}
봉인 함수
using UnityEngine;
public class BaseClass : MonoBehaviour
{
public virtual void Method()
{
Debug.Log("일반 함수");
}
}
public class MiddleClass : BaseClass
{
public sealed override void Method()
{
Debug.Log("봉인된 오버라이드 함수");
}
}
public class DerivedClass : MiddleClass
{
// sealed된 함수는 자식 클래스에서 override 불가
public override void Method()
{
Debug.Log("오버라이드 함수");
}
}
: 함수를 참조 → 대리자 역할
접근제한자 delegate 반환타입 이름(매개변수)
public delegate void MyDelegate();
델리게이트 할당과 실행
using UnityEngine;
public class StudyDelegate : MonoBehaviour
{
public delegate void MyDelegate();
public MyDelegate onDelegate;
void Start()
{
// Delegate 할당의 예전 방식
onDelegate= new MyDelegate(MethodA);
// Delegate 할당의 표준 방식
onDelegate= MethodA;
// 직접 실행 방식
onDelegate();
// 직접 실행과 동일한 방식
onDelegate.Invoke();
if (myDelegate != null) // null 체크가 없을 경우의 예외처리 방식
{
myDelegate.Invoke();
}
// null 체크 방식 -> 가장 안전한 방식
onDelegate?.Invoke();
}
private void MethodA()
{
Debug.Log("Method A 실행");
}
}
델리게이트 체인
using UnityEngine;
public class StudyDelegate : MonoBehaviour
{
public delegate void MyDelegate();
public MyDelegate onDelegate;
void Start()
{
onDelegate = OnMethodA;
onDelegate += OnMethodB;
onDelegate += OnMethodC;
onDelegate -= OnMethodB;
onDelegate?.Invoke();
}
private void OnMethodA()
{
Debug.Log("Method A 실행");
}
private void OnMethodB()
{
Debug.Log("Method B 실행");
}
private void OnMethodC()
{
Debug.Log("Method C 실행");
}
}
매개변수가 있는 Delegate
using UnityEngine;
public class StudyDelegate : MonoBehaviour
{
public delegate void MyDelegate(int a, int b);
public MyDelegate onDelegate;
void Start()
{
onDelegate = OnMethodA;
onDelegate += OnMethodB;
onDelegate += OnMethodC;
onDelegate -= OnMethodB;
onDelegate?.Invoke(10, 20);
}
private void OnMethodA(int a, int b)
{
Debug.Log("Method A 실행");
}
private void OnMethodB(int c, int d)
{
Debug.Log("Method B 실행");
}
private void OnMethodC(int e, int f)
{
Debug.Log("Method C 실행");
}
}
델리게이트의 매개변수 초기화
using UnityEngine;
public class StudyDelegate : MonoBehaviour
{
public delegate void MyDelegate(int n = 0);
public MyDelegate myDelegate;
void Start()
{
myDelegate += MethodA; // 사용 X
myDelegate += MethodB;
myDelegate?.Invoke(); // 사용 가능 O
myDelegate?.Invoke(10);
}
private void MethodA()
{
Debug.Log("Method A");
}
private void MethodB(int b)
{
Debug.Log("Method B");
}
}
외부 클래스에서 함수로 등록하는 경우
using UnityEngine;
public class ExternalClass : MonoBehaviour
{
private StudyDelegate studyDelegate;
void Awake()
{
studyDelegate.AddMethod(StopEvent1);
studyDelegate.AddMethod(StopEvent2);
}
private void StopEvent1()
{
Debug.Log("Stop Event 1");
}
private void StopEvent2()
{
Debug.Log("Stop Event 2");
}
}
외부 클래스에서 static 델리게이트에 접근하여 등록하는 경우
using UnityEngine;
public class ExternalClass : MonoBehaviour
{
void Awake()
{
StudyDelegate.onKeyDown += StopEvent1;
StudyDelegate.onKeyDown += StopEvent2;
}
private void StopEvent1()
{
Debug.Log("Stop Event 1");
}
private void StopEvent2()
{
Debug.Log("Stop Event 2");
}
}
OnEnable과 OnDisable을 활용한 안전한 이벤트 등록 / 해제 방식
using UnityEngine;
using UnityEngine.UI;
public class StudyDelegate : MonoBehaviour
{
public delegate void TimerStart();
public TimerStart onTimerStart;
public delegate void TimerEnd();
public TimerEnd onTimerEnd;
private float timer = 5f;
private bool isTimer = true;
void OnEnable()
{
onTimerStart += StartEvent;
onTimerEnd += EndEvent;
}
void Start()
{
onTimerStart?.Invoke();
}
void OnDisable()
{
onTimerStart -= StartEvent;
onTimerEnd -= EndEvent;
}
void Update()
{
if (!isTimer)
return;
timer -= Time.deltaTime;
if (timer <= 0f)
{
isTimer = false;
onTimerEnd?.Invoke();
}
}
private void StartEvent()
{
Debug.Log("타이머 시작");
}
private void EndEvent()
{
Debug.Log("타이머 종료");
}
}
delegate vs event 비교
| 특징 | delegate | event |
|---|---|---|
| 외부 호출 가능 여부 | 가능 | 불가능 (내부에서만 Invoke) |
| 외부에서 할 수 있는 것 | 추가/제거/호출 | 추가/제거만 가능 |
| 안전성 | 낮음 | 높음 |
일반적으로 사용했던 델리게이트 방식
using UnityEngine;
public class StudyEvent : MonoBehaviour
{
public delegate void InputKeyHandler();
public InputKeyHandler onInputKey;
void Start()
{
onInputKey += InputKeyEvent;
}
private void InputKeyEvent()
{
Debug.Log("Key Event");
}
}
외부 클래스에서 델리게이트 실행 가능
using UnityEngine;
public class ExternalClass : MonoBehaviour
{
public StudyEvent studyEvent;
void Awake()
{
studyEvent = FindFirstObjectByType<StudyEvent>();
}
void Start()
{
studyEvent.onInputKey += Event1;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
studyEvent.onInputKey?.Invoke();
}
}
private void Event1()
{
Debug.Log("Event 1");
}
}
event 키워드를 적용한 델리게이트
using UnityEngine;
public class StudyEvent : MonoBehaviour
{
public delegate void InputKeyHandler(string msg);
public event InputKeyHandler onInputKey;
void Start()
{
onInputKey += InputKeyEvent;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
onInputKey?.Invoke("Hello Unity");
}
}
private void InputKeyEvent(string msg)
{
Debug.Log(msg);
}
}
event를 사용했기 때문에 외부 클래스에서 델리게이트 실행 ❌ / ‘=’ 할당 ❌
using UnityEngine;
public class ExternalClass : MonoBehaviour
{
public StudyEvent studyEvent;
void Awake()
{
studyEvent = FindFirstObjectByType<StudyEvent>();
}
void Start()
{
studyEvent.onInputKey += Event1;
// studyEvent.onInputKey = Event1;
}
// void Update()
// {
// if (Input.GetKeyDown(KeyCode.Space))
// {
// studyEvent.onInputKey?.Invoke();
// }
// }
private void Event1(string s)
{
Debug.Log("Event 1 : " + s);
}
}
: EventArgs를 매개변수로 받는 Delegate
using System;
using UnityEngine;
public class StudyEventHandler : MonoBehaviour
{
public event EventHandler handler;
void OnEnable()
{
handler += MethodA;
}
void OnDisable()
{
handler -= MethodA;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
handler?.Invoke(this, EventArgs.Empty);
}
}
private void MethodA(object o, EventArgs e)
{
Debug.Log("Method A");
}
}