확장 메서드란?
확장 메서드(Extension Method)는 이미 존재하는 클래스에 메서드를 추가하는 독특한 기능입니다. 예를 들면 다음과 같은 방식으로 개발이 가능합니다.
string text = "HELLO!"
Debug.Log(text); // HELLO!
Debug.Log(text.RemoveL()); // HEO!
C#의 string에 RemoveL()이라는 메서드는 없습니다. 하지만 확장 메서드를 정의하면 별도의 클래스를 생성하지 않아도 새로운 기능을 쉽게 실행할 수 있습니다. 위 예제의 기능을 수행하는 확장 메서드는 아래와 같이 선언하면 됩니다.
public static class MyStringExtension
{
public static string RemoveL(this string str)
{
// str의 문자열 중 'L'을 삭제하는 코드 구현
return str.Replace("L", "");
}
}
여기에서 핵심은 정적 클래스 내에 선언된 정적 메서드로 확장이 된다는 것입니다. 또한 확장 메서드의 첫번째 인수에는 반드시 this 키워드를 가진 매개변수가 포함되어 있어야 합니다.
확장 메서드는 static 메서드다!
사실 확장 메서드를 작성한다고 해서 실제로 해당 클래스에 인스턴스 메서드가 추가 되는 것은 아닙니다. 실제로는 정적 메서드를 호출하는 것이지만 C#의 문법에 의해 마치 그렇게 보이는 것입니다. 아래의 아래의 두 코드는 같은 결과를 출력합니다. 확장 메서드를 사용하면 메서드의 호출을 더욱 간결하고 명확하게 할 수 있습니다.
// static 메서드의 형태로 호출.
MyStringExtension.RemoveL(text);
// 확장 메서드의 형태로 호출.
text.RemoveL();
확장 메서드는 바인딩 우선순위가 낮다
확장 메서드를 통해서 클래스의 메서드를 재정의할 수 없습니다. string의 Replace라는 메서드를 확장 메서드로 구현한다고 해서 이를 오버라이딩 할 수 없는 것이지요. 컴파일러는 클래스의 인스턴스 메서드에 먼저 바인딩을 시도한 후, 인스턴스 메서드를 찾을 수 없으면 확장 메서드에 바인딩을 합니다.
실제 프로젝트 적용 사례
Unity를 이용해 게임을 개발하던 중 화면에 출력되는 UI.Text들에 언어 설정에 따라 번역된 문자열을 적용하는 기능이 필요했습니다. 이미 작성된 코드에는 수많은 UI.Text 객체들이 있었기 때문에 번역된 문자열을 각각 할당하는 것은 굉장히 많은 반복 작업이 필요한 일이었습니다. 새로운 유틸리티 클래스를 만들거나 UI.Text를 상속받는 클래스를 만들어서 해결할 수도 있었지만 최소한의 코드 변경으로 해당 기능을 구현하고 싶었습니다.
이 문제를 해결하기 위해 확장 메서드를 사용했습니다. 다음과 같은 코드를 작성하여 UI.Text가 SetTerm이라는 메서드를 인스턴스 메서드처럼 실행할 수 있도록 구현했습니다.
public static class TextExtension
{
public static void SetTerm(this Text text, string term)
{
// 번역 기능을 수행하는 컴포넌트를 가져온다.
var localize = text.transform.GetComponent<I2.Loc.Localize>();
if(localize == null)
{
Debug.LogError($"[TextExtension] 현재 Text component에 I2.Loc.Localize가 추가되어 있지 않음");
return;
}
// 번역 컴포넌트에 번역을 위한 키값을 입력한다. 이를 통해 번역된 문자열이 UI.Text에 자동으로 할당한다.
localize.Term = $"{term}";
}
}
그 결과 아래와 같이 매우 간단한 형태로 원하는 기능을 구현할 수 있었습니다.
public class AlertView : MonoBehaviour
{
public Text m_Title;
public Text m_Message;
/* ... */
public void Show(string titleKey, string messageKey)
{
m_Title.SetTerm(titleKey);
m_Message.SetTerm(messageKey);
/* ... */
}
}
참고 자료
Extension Methods (C# Programming Guide) (링크)