[C#] 3. 생성자와 this / this() 키워드

반응형
반응형

#3 생성자와 this / this() 키워드

 

[학습목표]

  • 생성자의 개념과 사용방법에 대한 이해
  • this 키워드 사용방법 숙지
  • this() 키워드 사용방법 숙지

[목차]

  • 1.1 생성자가 필요한 이유
  • 1.2 생성자
  • 2.1 this 키워드
  • 2.2 this() 키워드

* 개인적인 공부 기록용으로 작성한 글이기에, 잘못된 내용이 있을 수 있습니다.


#1.1 생성자가 필요한 이유

생성자 문법에 대해 알아보기 전에, 우선 생성자가 왜 필요한지에 대해서 알아 보도록 하겠습니다. 아래 코드를 봐주세요.

namespace TextRpg
{
    class Knight
    {
        public int hp;
        public int atk;

    }

    class Program
    {
        static void Main(string[] args)
        {
            Knight knight = new Knight();
            knight.hp = 100;
            knight.atk = 10;
        }
    }
}

Knight 클래스를 정의한 뒤, Main 함수부에서 knight 객체의 멤버함수 hp, atk 값을 각각 초기화 해 주고 있습니다.

그런데 만약 hp와 atk값을 실수로 초기화 하지 않으면, hp와 atk가 0인 기사 플레이어가 월드에 생성되게 됩니다.

또한, Main 함수부에서 객체의 모든 값을 초기화 하는 것은 가독성과 유지보수 면에서도 매우 비효율 적입니다.

이러한 상황을 해결하기 위해 C#은 생성자라는 문법을 제공합니다.

 

#1.2 생성자

생성자를 이용하면 자동으로 객체의 값을 초기화 해 줄 수 있습니다. 생성자의 사용 방법은 다음과 같습니다.

접근지정자 클래스이름 {}

생성자의 이름은 무조건 클래스의 이름과 동일해야만 합니다. 또한, void / int 와 같은 반환형은 올 수 없습니다.

아래는 생성자를 사용한 예시입니다.

namespace TextRpg
{
    class Knight
    {
        public int hp;
        public int atk;

        public Knight()
        {
            hp = 100;
            atk = 10;
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            Knight knight = new Knight();
        }
    }
}

이렇게 생성자 문법을 이용하면, 혹여나 객체의 값을 초기화 하지 않았다 하더라도, 자동으로 생성자가 멤버값을 초기화 해 줍니다. 그리고 Main 함수부의 코드도 줄어서 가독성도 좋아졌습니다.

 

#2.1 this 키워드

생성자는 여러개 만들 수 있습니다. hp를 인자로 받는 생성자를 하나 더 만들어 봅시다.

    class Knight
    {
        public int hp;
        public int atk;

        public Knight()
        {
            hp = 100;
            atk = 10;
        }

        public Knight(int hp)
        {
            hp = hp;
        }

    }

하지만 다음과 같은 CS1717 에러 메시지가 출력됩니다.

이는 파라미터로 받은 hp와 클래스에 존재하는 hp멤버변수의 이름이 같기 때문에 발생하는 오류입니다. 이 것을 해결하기 위해선 this 키워드를 사용하면 됩니다. this는 클래스에 존재하는 멤버변수를 가리키는 키워드입니다. 다음과 같이 선언해 주면 해결됩니다.

    class Knight
    {
        public int hp;
        public int atk;

        public Knight()
        {
            hp = 100;
            atk = 10;
        }

        public Knight(int hp)
        {
            this.hp = hp;
        }

    }

이로써, 클래스에 존재하는 hp와, 파라미터 hp를 구별이 가능하게 됐습니다.

 

#2.2 this()

그런데, 여전히 문제가 있습니다. 만약 두 번째 생성자를 호출 했다면, hp의 값을 채워졌는데 atk의 값은 여전히 채워지지 않았기 때문입니다. 이를 해결하기 위해서 this.atk = atk; 와 같이 선언해 주면 되지만, 멤버변수가 몇십개로 매우 많은 상황이라면 하나하나 작성해 주는 것은 매우 비효율 적일 것입니다.

여기서 this() 키워드를 사용하면 문제를 해결할 수 있습니다. this() 키워드는 생성자를 특정하여 , 먼저 호출을 해줍니다.

this() 키워드의 사용방법은, 생성자 오른쪽에 콜론(:)과 함께 this()를 작성해 주면 됩니다.

namespace TextRpg
{
    class Knight
    {
        public int hp;
        public int atk;

        public Knight()
        {
            hp = 100;
            atk = 10;
            Console.WriteLine("Knight() 호출");
        }

        public Knight(int hp) : this()
        {
            this.hp = hp;
            Console.WriteLine("int Knight() 호출");
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            Knight knight = new Knight(50);
        }
    }
}

코드의 흐름을 그림으로 표현해 보았습니다.

두 번째 생성자가 실행되기 전에, this() 키워드를 만나서, 첫 번째 생성자를 먼저 실행합니다.

따라서 최종적으로 hp = 50 , atk = 10 인 knight 객체가 생성되게 됩니다.

 

물론, 아래 처럼 원하는 생성자를 특정해서 사용하는 것도 가능합니다. 

namespace TextRpg
{
    class Knight
    {
        public int hp;
        public int atk;

        public Knight()
        {
            hp = 100;
            atk = 10;
            Console.WriteLine("Knight() 호출");
        }

        public Knight(int hp)
        {
            this.hp = hp;
            Console.WriteLine("int Knight() 호출");
        }

        public Knight(int hp, int atk) : this(hp)
        {
            this.hp = hp;
            this.atk = atk;
            Console.WriteLine("int int Knight() 호출");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Knight knight = new Knight(50,10);
        }
    }
}
[출력결과]
int Knight() 호출
int int Knight() 호출

반응형

댓글

Designed by JB FACTORY