C# 클래스나 변수를 선언할때 다음과 같은 접근 제한자가 있다.

  • public : 외부클래스(스크립트)에서 접근가능, 인스펙터에 노출됨
  • private : 동일클래스에서만 접근가능. 외부접근 불가, 인스펙터에 노출안됨
  • protected: private과 동일하게 외부접근 불가능하고 상속받은 파생 클래스에서만 접근가능
  • internal : 같은 어셈블리에서만 접근가능. class의 경우 접근제한자를 생략하면 internal이 기본값으로 설정

액세스 한정자는 멤버 또는 형식의 선언된 접근성을 지정하는데 사용되는 키워드

키워드 접근성
public 제한 없음
protected 포함 및 파생
internal 동일 어셈블리로 제한
protected internal 동일 어셈블리 또는 다른 어셈블리여도 포함하는 클래스에서 파생된 형식
private 포함
private protected 포함 or 동일 어셈블리 내의 포함하는 클래스의 파생 ( C# 7.2 이상 )

* 네임 스페이스에는 액세스 한정자가 허용되지 않음 

public class A { }
// 동일 어셈블리에서는 internal만 사용할 경우 public과 접근 제어 수준이 동일함
internal class B { } 

// protected, protected internal, private, private protected는 namespace에는 허용되지 않기 때문에 에러
protected class C { }

* 멤버 선언이 발생한 구문에 따라 특정 액세스 한정자만 허용

- 멤버가 다른 형식 내에 중첩되면 해당 엑세스 가능 영역은 엑세스 가능성 수준 및 한 수준 위 형식의 엑세스 가능 영역에 의해 결정됨

public class A{
    private class AA {
		public int x;
    }
}

public class B {
    void Test() {
        // AA Class가 private 이기 때문에 AA.x가 public 이여도 외부에서 접근할 수 없음
        A.AA aa = new A.AA();
    }
}

* 기본 멤버 액세스 가능성 및 멤버의 허용된 액세스 가능성

구문 기본 멤버 엑세스 멤버의 허용된 액세스
enum public none
class  private  public / protected / internal / private / protected internal, private protected
interface public public / protected / internal / *private ( 기본 구현 필요 ) / protected internal, private protected
struct private 상속이 안되기 때문에 protected는 제외됨

public / internal / private 

* protected

class A
{
    protected int x = 1;
}

class B : A
{
    void Start()
    {
        A a = new A();
        B b = new B();

        // x에 접근할 수 없기 때문에 에러
        a.x = 1;

        // x에 접근할 수 있기 때문에 정상
        x = 2;
    }
}

* internal

// EveryDayDevup-Framework 어셈블리
// 같은 어셈블리에서는 접근이 가능
internal class A {
    public static int x = 1;
}

class C{
    void Test() {
		A.x = 2;
    }
}


// Assembly-CSharp
class B {
    void Start() {
    	// 어셈블리가 다르기 때문에 A에 접근할 수 없음 
        A.x = 3;
    }
}
// internal class를 public으로 변경하고 멤버를 internal로 변경
public class A
{
	internal static int x = 1;
}

class C
{
	void Test()
    {
		A.x = 2;
    }
}


class B : 
{
    void Start()
    {
        A a = new A();
    	// 인스턴스 생성은 가능하지만
        // internal로 설정한 x에 접근할 수 없음 
        a.x = 2;
    }
 }

* protected internal

// EveryDayDevup-Framework
// 같은 어셈블리에 있는 C는 A.x의 접근할 수 있음
public class A
{
	internal int x = 1;
}

public class C 
{
	void Test()
    {
		x = 3;
    }
}

// Assembly-CSharp
// 다른 어셈블리에 있는 B클래스는 상속을 해도 A.x의 접근할 수 없음
class B : A
{
    void Start()
    {
        x = 2;
    }
}
// EveryDayDevup-Framework
// protected internal을 사용하면 다른 어셈블리의 파생 클래스에서 x의 접근이 가능
// protected internal은 멤버에만 사용할 수 있음
public class A
{
	protected internal int x = 1;
}

// Assembly-CSharp
class B : A
{
    void Start()
    {
     	// protected internal은 상속 시 다른 어셈블리에서 접근이 가능
        x = 2;
    }
}

* private

class A
{
    private int x;
    
    public int GetX() {
    	return x;
    }
}

class B
{
    void Test()
    {
        A a = new A();
        // private는 선언된 클래스 또는 구조체의 본문에서만 접근 가능
        // a.x의 접근할 수 없기 때문에 에러
        a.x;
        
        // A에서 x를 접근할 수 있도록 해줘야함
        a.GetX();
    }
}

* private protected

// EveryDayDevup-Framework
// 동일 어셈블리의 파생 클래스에서는 접근이 가능
public class A {
	private protected int x = 1;
}

public class C : A{
	void Test() {
		x = 2;
    }
}

// Assembly-CSharp
class B : A {
    void Test(){
    	// 다른 어셈블리에서는 상속을 받아도 x에 접근할 수 없음 
        x = 3;
    }
}

 

'유니티게임강좌 > 주인공 캐릭터 제작' 카테고리의 다른 글

[Player제작] 캐릭터 회전 - Rotate  (0) 2023.02.25
Assembly  (0) 2023.02.25
[Player제작] 캐릭터의 이동  (0) 2023.02.25
[Player제작] InputManager  (2) 2023.02.25
[Player제작] 유니티 Class 종류  (0) 2023.02.25

+ Recent posts