Sugar

[Unity] Property - get/set

by Sugar0810

📚 프로퍼티(Property)

외부에서 클래스 변수에 값을 할당할 때

변수의 값이 항상 올바르도록 강제할 수 있다.

변수의 값이 변경되었을 때를 감지, 그 값에 영향을 받는 다른 함수나 동작을 실행하도록 구현 가능

해당 변수를 이곳 저곳에서 가져가 사용하는 함수에서마다 조건들을 보는 것을 줄여준다. (최적화)

변수처럼 선언되지만, 함수처럼 중괄호로 묶인 형태

📄 get
외부에서 해당 프로퍼티에 접근하여 읽어야 하는 상황에서 호출됨

📄 set
외부에서 해당 프로퍼티에 접근하여 값을 할당하는 상황에서 호출됨

/// 프로퍼티 구현 : 정해진 범위 내의 값 할당
public class Example : MonoBehaviour
{
    // '_hp' 변수에 대한 프로퍼티
    public float HP
    {
        get
        {
            return _hp;
        }
        set
        {
            if(_hp >= 0f && _hp <= 100f)
            {
                _hp = value;
            }
        }
    }
    private float _hp;  // 실제 내부 클래스 변수
}

/// 외부에서 사용할 때
Example example = new Example();
example.HP = 10f;         // 올바른 값 할당
// example.HP = 5000f;     값이 할당되긴 하나, 프로퍼티 내부에서 필터링된다.
/// 프로퍼티 구현 : 특정 이벤트 발생
public float HP
{
    get
    {
        return _hp;
    }
    set
    {
        if( _hp >= 0f && _hp <= 100f )
        {
            float preHp = _hp;
            _hp = value;

            if (!Mathf.Approximately(_hp, preHp))
                OnChangeValue();
        }
    }
}

 

📖 읽기 전용 프로퍼티

'private set' 키워드가 없을 땐 내/외부 모두 참조할 수 없다.

public class Example : MonoBehaviour
{
    private float _hp;
    public float HP
    {
        get
        {
            return _hp;
        }
    } // 읽기 전용
}

읽기 전용 &rarr; 값 할당 불가

 

📖 쓰기 전용 프로퍼티

get 접근자가 없으므로 외부에서 참조할 수 없다.

public class Example : MonoBehaviour
{
    private float _hp;
    public float HP
    { // 쓰기 전용
        set
        {
            _hp = value;
        }
    }
}

쓰기 전용 &rarr; 참조 불가

 

📖 외부에서는 읽기 전용이고, 내부에서 조건부 값 할당을 하고 싶을 경우

public class Example : MonoBehaviour
{
    private float _hp;
    public float HP
    {
        get 
        { 
            return _hp;
        }
        private set
        {
            if(_hp >= 0f && _hp <= 100f)
            {
                _hp = value;
            }
        }
    }
}

 

📖 자동 구현 프로퍼티

단순히 변수 값 할당, 반환만 할 때 사용

public class Example : MonoBehaviour
{
   public float HP { get; set; }  // 자동 구현 프로퍼티
}

class ExternalClass
{
    public void Function()
    {
        Example example = new Example();
        example.HP = 50f; // 프로퍼티 그 자체를 변수로 사용
    }
}

 

 

📖 프로퍼티에 대한 사용 팁

// 1. 프로퍼티는 선언과 동시에 필드에 대한 초기화 가능
public float HP { get; set; } = 100f;


// 2. 클래스 객체를 생성할 때도 초기화 가능
Example example = new Example() { HP = 100f };


// 3. 무명 형식 지원
var example = new { HP = 100f };   // 단, 한번 값 할당하면 변경 불가

 

📖 초기화 전용 자동 구현 프로퍼티

C# 9.0에 도입된 기능(하지만 유니티에선 미지원 상태)

기존 방식에선 프로퍼티를 읽기 전용으로 선언하는 방법이 생성자를 통해 필드를 초기화, 그 필드에 접근하는 프로퍼티는 get 접근자만 갖도록 해야하는 번거로움이 있었다.

/// 기존 방식
class Monster
{
    private string name;
    private int hp;
    private int damage;
    
    // 생성자 생성
    public Monster(string name, int hp, int damage)
    {
        this.name = name;
        this.hp = hp;
        this.damage = damage;
    }
    
    // get만 가짐
    public string Name { get {return name;} }
    public int HP { get {return hp;} }
    public int Damage { get {return damage;} }
}

이제 자동 구현 프로퍼티에 init 접근자를 사용하면서 해결할 수 있다.

set 접근자처럼 외부에서 프로퍼티 변경 가능하나, 객체 초기화를 할 때만 가능하다.

초기화 이후부턴 get만 수행 가능

ReadOnly 필드에도 접근 가능

// 초기화 전용 자동 구현 프로퍼티
class Monster
{
    public string Name { get; init; }
    public int HP { get; init; }
    public int Damage { get; init; }
}

Monster monster = new Monster
{
    Name = "Slime",
    HP = 500,
    Damage = 10
};
        
// monster.HP = 1000;   컴파일 오류. 초기화 후 수정 불가
public class Person
{
    private readonly string firstName;
    private readonly string lastName;
    
    public string FirstName 
    { 
        get => firstName; 
        init => firstName = (value ?? throw new ArgumentNullException(nameof(FirstName)));
    }
    public string LastName 
    { 
        get => lastName; 
        init => lastName = (value ?? throw new ArgumentNullException(nameof(LastName)));
    }
}

 

 

📚 유니티에서의 특징

📄 기본적으로 인스펙터에서는 보이지 않으므로 추가 조치가 필요하다.

📄 init 초기화 프로퍼티는 현재까지 유니티에서 미지원이다.

C# 9.0에서 미지원하는 Init Only setters

 

📚 참고사이트

블로그의 정보

Sugar

Sugar0810

활동하기