목표
- 접근 한정자(access modifiers 혹은 visibility modifier)에 대해 알아보자.
접근 지시자는 강력하지만, 현실은 Public
접근 한정자 (access modifiers)
- 접근 한정자는 외부로부터 접근을 제한할 때 사용된다.
- 아래 설명에서 동일 어셈블리란 exe나 dll 등의 빌드 결과물을 말한다.
접근 한정자 | 설명 |
public | 모든 접근을 허용한다. |
protected | 파생형 클래스에서만 접근을 가능하게 한다. |
private | 동일 클래스 내의 멤버만 접근 가능하다. |
internal | 동일한 어셈블리에서만 접근 가능하다. 주로 SDK 개발에 사용되는 키워드이다. |
protected internal | 동일한 어셈블리 또는 파생형에서만 접근 가능하다. internal의 접근을 제한적으로 허용하기 위해 사용된다. |
private protected | 동일한 클래스 또는 동일한 어셈블리 내의 파생형에서만 접근 가능하다. |
public & protected & private
public class ProtectedClass()
{
public ProtectedClass()
{
// private 함수는 오직 함수가 정의된 클래스 내부에서만 접근할 수 있다.
CallPrivate();
}
private void CallPrivate()
{
// CallPublic()은 어디서든지 호출할 수 있다.
}
public void CallPublic()
{
// CallPublic()은 어디서든지 호출할 수 있다.
}
protected void CallProtected()
{
// CallPublic()은 어디서든지 호출할 수 있다.
}
}
// ProtectedClass를 상속 받은 파생형 객체
public class DerivedProtectedClass : ProtectedClass
{
public void CallParentProtected()
{
base.CallProtected();
}
}
public class SampleScript : MonoBehaviour
{
ProtectedClass pClazz = new ProtectedClass();
DerivedProtectedClass dpClazz = new DerivedProtectedClass();
public void Start()
{
// public 함수는 노출되지만, protected는 노출되지 않는다.
pClazz.CallPublic();
// 상속을 받았으니 당연히 public 함수가 노출된다.
dpClazz.CallPublic();
// 상속을 받아도 protected의 경우 외부에서 호출할 수 없다.
// 좋은 방법은 아니지만 파생형 클래스에서 부모 클래스에 접근하는
// public 함수를 정의하면 외부에서도 protected에 접근 가능하다.
// 이러면 접근 제한자를 쓰는 의미가 없잖아?
dpClazz.CallParentProtected();
}
}
internal
- internal을 테스트해보기 위해서는 Unity C#를 DLL을 만들어보면 된다.
- Unity C# 코드 DLL 만들기
- 이렇게 만들어진 DLL은 Unity Script 뭉치로 보면 된다.
- DLL을 만들었다면 SampleScript에서 DataCenter의 함수들을 호출해보자.
- CallPublic 함수만 노출된다.
- CallInternal 함수는 DataCenter 내부에서만 사용 가능하게 만든 함수 이므로 이렇게 노출되는게 정상이다.
VisualStudio에서 Unity용 DLL로 빌드한 DataCente.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Data
{
public class DataCenter
{
public void CallPublic()
{
Debug.Log("public method call!!");
}
protected void CallProtected()
{
Debug.Log("protected method call!!");
}
private void CallPrivate()
{
Debug.Log("private method call!!");
}
internal void CallInternal()
{
Debug.Log("internal method call!!");
}
protected internal void CallProtectedInternal()
{
Debug.Log("protected internal method call!!");
}
}
}
DataCenter를 호출하는 Unity Sample Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Data;
public class SampleScript : MonoBehaviour
{
DataCenter dataCenter = new DataCenter();
// Start is called before the first frame update
void Start()
{
dataCenter.CallPublic();
}
}
- 이 상황에서 internal을 호출하려면 InternalsVisibleToAttribute을 사용해야 한다.
- 이는 internal의 접근 제어 효과를 깨트리는 방법이다.
- C++ 프로젝트에서도 간혹 Friend 키워드가 있다고 사용하는 사람들이 있는데,
한번 끌려가서 비오는날 Unix Timestamp 만큼 처맞아 보야 - 정말 필요한 상황이 아니면 쓰지 말도록 하자.
- C++ 프로젝트에서도 간혹 Friend 키워드가 있다고 사용하는 사람들이 있는데,
protected internal
- DataCenter를 상속 받으면 protected internal에 접근할 수 있다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Data;
public class DerivedDataCenter : DataCenter
{
public DerivedDataCenter()
{
base.CallProtectedInternal();
}
}
private protected
- 이건 C# Version 7.2에 추가된 문법이다.
- Unity 2019.3 이상 버전에서는 C# 8.0을 지원하지만, 2018.x 버전에서는 지원하지 않는다.
- 따라서 범용성이 떨어져, Unity C#에서 private protected 구현은 Pass!!
정리
사실 게임 개발에는 주로 public이나 public이나 public이 사용된다.- 사실 게임 개발에는 주로 public, protected, private만 사용된다.
- internal이나 protected internal은 Plugin 제작시 사용되는데, 7년 일하면서 protected internal은 책에서만 본것 같다.
'프로그래밍 > Unity C#' 카테고리의 다른 글
[Unity] Tutorial 06 - Intermediate Scripting (Information Hiding) (0) | 2020.01.20 |
---|---|
[Unity] Tutorial 06 - Intermediate Scripting (Method Hiding) (0) | 2020.01.17 |
[Unity] Tutorial 06 - Intermediate Scripting (Sealed) (0) | 2020.01.17 |
[Unity] Tutorial 06 - Intermediate Scripting (Interface) (0) | 2020.01.17 |
[Unity] Tutorial 06 - Intermediate Scripting (Virtual) (0) | 2020.01.17 |