2022. 4. 14. 18:47ㆍProgramming language/C#
- 목차
서론
이전에 쓴 글 중 [C#] Boxing/Unboxing (박싱/언박싱)에 관한것이 있었습니다. 이때 한 이야기 중, 타입이 명시적이다라는 것이 있었는데요. 오늘은 이와 연관이 깊은 제네릭(Generic)에 관해 써보려 합니다.
제네릭(Generic)
제네릭(Generic)의 사전적 의미는 '포괄적인, 통칭(총칭)의'라는 뜻입니다. 이 말 고도 '일반적인'이라는 뜻 도 있습니다. 프로그래밍적으로 보자면, '아직 정해지지 않았지만, 어쨌든 타입을 총칭'한다라는 뜻이 아닐까 싶습니다.
예를 들어 보겠습니다. 아래는 싱글톤객체를 instance로 생성하는 일반적인 로직입니다.
public class CustomSingleton : MonoBehaviour
{
private static object _syncobj = new object();
private static CustomSingleton _instance = null;
public static CustomSingleton Instance{
get {
if (_instance == null)
{
lock (_syncobj) {
if (_instance == null)
{
GameObject app = new GameObject(typeof(CustomSingleton).ToString());
_instance = app.AddComponent<CustomSingleton>();
DontDestroyOnLoad(app);
}
}
return _instance;
}
return _instance;
}
}
}
프로젝트에서 몇가지 싱글톤 객체를 사용하는데, 매번 위와 같은 코드를 반복해서 생성해줄까요? 기능도 비슷하고, 다른 것이라고는 오직 '타입'뿐 입니다. 싱글톤 객체로 만들어줄 객체의 타입 말이죠. 여기서 한 가지 방법을 생각해 볼 수 있습니다. 생성할 로직 부분을 상속받게 하는 법입니다.
public class CustomSingleton02 : CustomSingleton
{
}
public class CustomSingleton03 : CustomSingleton
{
}
음... 해보니, 뭔가 이상합니다. 상속을 받았다지만 Singleton의 타입이 되는 것은 오로지 CustomSingleton입니다. CustomSingleton02, 03의 싱글톤이 아닌 것이지요. 만약 제대로 Singleton의 특성과 로직을 이용하고 싶다면 어떻게 해야 할까요?
싱글톤을 생성하는 로직을 작성하고, 싱글톤이 될 타입의 결정을 제네릭으로 두는 것입니다. 타입을 포괄하여 결정을 미룬다고 생각하시면 됩니다. 아래는 바뀐 코드입니다.
public class CustomSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static object _syncobj = new object();
private static T _instance = null;
public static T Instance{
get {
if (_instance == null)
{
lock (_syncobj) {
if (_instance == null)
{
GameObject app = new GameObject(typeof(T).ToString());
_instance = app.AddComponent<T>();
DontDestroyOnLoad(app);
}
}
return _instance;
}
return _instance;
}
}
}
'T'라는 부분의 제네릭 타입으로 둔다는 의미의 사용법입니다. 즉, T라는 타입의 싱글톤 클래스라는 뜻이죠.
T라는 타입은 CustomSingleton02도 될 수 있고 CustomSingleton03이 될 수도 있습니다. 아래와 같이 이용할 수 있습니다.
public class CustomSingleton02 : CustomSingleton<CustomSingletoe02>
{
}
public class CustomSingleton03 : CustomSingleton<CustomSingletoe02>
{
}
이렇게 제네릭 타입을 이용하는 클래스를 상속시켜주면, 상속받은 녀석이 타입을 결정할 수 있게 되는 것입니다.
참고로 where T : MonoBehaviour은 제약조건을 설정하는 부분입니다. 제네릭 타입의 경우, 타입의 범위를 제약해주지 않으면 제대로 사용할 수 없습니다. 제네릭하게 사용할 타입이 ValueType인지 RefType인지조차 모를 테니 말이죠.
public class CustomSingleton <T> : MonoBehaviour where T : MonoBehaviour
을 해석해 보자면, '싱글톤 객체를 생성할 것인데 타입은 MonoBehaviour타입에 한정된다.'입니다.
마무리
일반적으로 제네릭의 관한 설명을 보면, 아직 모양이 정해지지 않은 틀에 비유를 많이 합니다. 적절한 설명인 것 같습니다. 아직 타입이 어떤 모양일지 정해지지 않아, 나중에 반죽하겠다는 뜻으로 해석하면... 괜찮은 설명 같습니다.
'Programming language > C#' 카테고리의 다른 글
[C#]닷넷(.Net)의 구성 요소 (0) | 2022.08.09 |
---|---|
[C#]닷넷(.Net)에 관하여 (0) | 2022.08.07 |
[C#]컬렉션(Collection) (0) | 2022.04.19 |
[C#]가비지 컬렉터(Garbage collector) (0) | 2022.04.12 |
[C#]Boxing/Unboxing (박싱/언박싱) (0) | 2022.04.12 |