bdfgdfg

[C#] 프로퍼티(갓) 본문

게임프로그래밍/C#

[C#] 프로퍼티(갓)

marmelo12 2022. 4. 19. 15:28
반응형

클래스의 멤버 변수를 public으로 열어놓는 것은 지양해야 한다.

 -> 객체지향의 은닉성/캡슐화를 지키기 위해.

위와 같은 이유로. C++에서는 해당 객체의 멤버를 가지고 오기 위해 멤버 함수로 Get~과 같은 함수를 통해 해당 변수를 가져오거나, 객체의 멤버 변수를 수정하기 위해서는 Set~과 같은 함수를 통해 수정했다.

 

C#에서는 위와 같이 번거롭게 Get, Set함수를 따로 만들지 않더라도, 이 프로퍼티를 이용하면 간단하게 해결 가능하다.

(매우 편리)

 

프로퍼티의 사용방법은 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class 클래스명
{
    데이터타입 필드명;
    접근지정자 데이터형식 프로퍼티명
        {
        get
        {
            return 필드명;
        }
        set
        {
            필드명 = value; // value는 set접근자의 암묵적 매개변수로 간주.
        }
    }
}
cs

즉 위의 형식을 참고하면서 만들어보면

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Test
{
 
    private int m_myData = 10;
    public int MyData
    {
        get 
        { 
            return m_myData; 
        }
        set 
        { 
            m_myData = value; 
        }
    }
}
 
 
class Program
{
    static void Main(string[] args)
    {
        Test test = new Test();
        test.MyData = 50;
    }
}
 
cs

위와 같이 만들 수 있다.

MyData는 프로퍼티이고, 대입 연산자를 통해 값을 바로 대입하고 있다. 마치 실제 멤버 변수에 접근해 값을 수정하는 것과 같이 보이는데 실제로는

프로퍼티의 set에 접근하고 있다.

 -> 참고로 프로퍼티 선언 문법에서 set과 get을 일컬어 접근 자라고 한다.

 

반대로 int data = test.MyData; 와 같이 해당 객체의 멤버 변수에 직접 접근해 다른 변수에 값을 할당하는 것처럼 보이지만.

실제로는 get접근자를 통해 값을 얻어오고 있는 것.

 

또한 해당 멤버 변수를 수정하고 싶지 않다면 set접근자를 구현하지 않으면 된다. 그럼 해당 프로퍼티는 읽기 전용 프로퍼티가 된다.

 -> 물론 최소한 get접근자는 구현되어 있어야 한다.

 -> 또한 get접근자를 구현하지 않고 set접근자만을 구현하는 것도 가능하다.

 

자동 구현 프로퍼티

이것 또한 엄청 편리한 기능이다.

사실 위에서 보면 get, set접근자가 하는 일은 get { return 멤버 변수 } set { 멤버변수 = value; } 이게 전부다.

이것도 편리하고 간단하지만, 좀 더 간단하게 사용도 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Test
{
    //public int m_myData = 10; 이제 필드(멤버 변수)를 구현할 필요가 없다.
    public int MyData { get; set; }
}
 
 
class Program
{
    static void Main(string[] args)
    {
        Test test = new Test();
        Console.WriteLine(test.MyData);
        test.MyData = 50;
        Console.WriteLine(test.MyData);
    }
}
 
cs

저렇게 자동 구현 프로퍼티를 이용할 경우. 멤버 변수를 선언할 필요도 없으며, 자동 구현 프로퍼티 한 줄이면

멤버 변수 선언, get, set접근자 구현이 자동으로 구현이 된다.

 -> 심지어 해당 프로퍼티의 초기값도 0으로 알아서 초기화가 된다.

근데 0으로 초기화되는 건 별로인데, 내가 다른 값으로 초기화를 시키고 싶을 땐 어떻게 할까.

프로퍼티 뒤에다가 바로 초기화 값을 넣어주면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Test
{
    //public int m_myData = 10; 이제 필드(멤버 변수)를 구현할 필요가 없다.
    public int MyData { get; set; } = 100;
    public string MyString { get; set; } = "Hello World!";
}
 
 
class Program
{
    static void Main(string[] args)
    {
        Test test = new Test();
        Console.WriteLine(test.MyData);
        Console.WriteLine(test.MyString);
    }
}
 
cs

진짜 너무 편리하다. 

 

이게 가능한 이유가 뭘까? 바로 C# 컴파일러가 자동으로 멤버 변수를 private으로 만들어준다.

 

또한 객체를 생성할 때 프로퍼티를 초기화하는 것도 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Program
{
    static void Main(string[] args)
    {
        // 객체 생성과 동시에 프로퍼티를 초기화.
        Test test = new Test()
        { 
            MyString = "Initialization",
            MyData = 500
        };
 
        Console.WriteLine(test.MyData);
        Console.WriteLine(test.MyString);
    }
}
 
cs

프로퍼티가 생성된 순서 같은 건 지킬 필요 없고, 내가 초기화하고 싶은 프로퍼티만을 초기화하는 것도 가능하다.

 

무명 형식(데이터 타입, 자료형)

기본적으로 데이터 형식은 여러 가지가 있다. 언어에서 제공하는 int, double, string 혹은 사용자 정의 자료형인 struct, class 형식들. 

여기서는 이름이 없는 형식. 즉 무명 형식이 C#에는 존재한다.

 

무명 형식은 형식의 선언과 동시에 인스턴스를 할당한다. 

1
2
3
4
5
6
7
8
9
class Program
{
    static void Main(string[] args)
    {
        var proInstance = new { Data = 10, Name = "Test" };
        Console.WriteLine($"{proInstance.Data},{proInstance.Name}");
    }
}
 
cs

무명 형식의 프로퍼티에 할당된 값은 변경이 불가능하다.

 -> 무명 형식의 인스턴스가 만들어지면 읽기 전용.

 -> 나중의 LINQ와 함께 사용 시 유용하게 사용 가능.

 

인터페이스와 추상 클래스의 프로퍼티

인터페이스에서 메서드뿐만 아니라, 프로퍼티, 인덱서, 이벤트 등도 선언할 수 있다고 했다.

 

프로퍼티만 보자.

인터페이스에서 프로퍼티 선언은 자동 구현 프로퍼티 선언과 모습이 똑같다.

1
2
3
4
5
class Product : IProduct
{
    private string productName;
    public string ProductName { get { return productName; }  set { productName = value; } }
}
cs

 

추상 클래스에서는 선언 부만 가지는 인터페이스와는 달리 구현 부도 가진다. 물론 인터페이스처럼 구현되지 않은 프로퍼티도 선언 가능하다.

 -> 추상 클래스에서는 이것을 추상 프로퍼티라고 한다.

 -> 추상 프로퍼티는 인터페이스의 프로퍼티 선언과 다를 게 없다. (단지 파생 클래스에서 해당 기능의 구현을 강제할 뿐)

 

그럼 추상 프로퍼티는 어떻게 선언할까. 인터페이스와 달리 구현을 비워놓은 것만으로는 불가능하다.

 -> 클래스에서 선언했으니(추상 클래스라도) C# 컴파일러가 자동 구현 프로퍼티로 간주하고 구현을 채워 넣는다.

 

간단하다. 추상 클래스를 선언한것처럼. 추상 메소드를 선언한것처럼 프로퍼티도 abstract 지정자를 이용하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
abstract class Test2
{
    public abstract int abstractProperty
    {
        get; set;
    }
}
 
class MyClass : Test2
{
    int m_test = 50;
    public override int abstractProperty 
    { 
        get { return m_test; } 
        set { m_test = value; } 
    }
}
 
cs
반응형

'게임프로그래밍 > C#' 카테고리의 다른 글

[C#] 일반화(제네릭) 프로그래밍  (0) 2022.04.21
[C#] 인덱서(Indexer)  (0) 2022.04.21
[C#] 인터페이스,추상클래스  (0) 2022.04.19
[C#] 부모 자식 사이의 형 변환 (is,as)  (0) 2022.04.18
[C#] ref,out 키워드  (0) 2022.04.18
Comments