티스토리 뷰
C#을 공부해본 사람이라면 아마 생성자라는 단어를 들어본 적이 있을 것이다. 생성자란, 객체를 생성할 시에 객체의 속성들을 간단히 초기화할 수 있게 하는 목적을 가지고 있다. 따로 반환형은 표시하지 않고, 클래스의 이름과 같게 선언되기 때문에 객체를 선언할 때 함께 호출된다. 따라서 인위적으로 호출을 할 수 없다. 또한, 오버로딩이라 하는 기능을 허용하는 특징을 가지고 있다.
사용 방법은 아래와 같다.
# 생성자 사용을 하지 않고 객체를 초기화 할 경우
클래스명 object = new 클래스명()
object.초기화메소드(초기화 인수 ...);
# 생성자 사용해 객체를 초기화 할 경우
클래스명 object = new 클래스명(초기화 인수 ...);
사용법이 많이 어렵지 않다. 실제 개발에서 예를 들어 사용 예시를 보여주겠다.
public class Player
{
private string name;
private int winCount;
private int currentKbb;
// Player의 생성자
public Player(string name)
{
this.name = name;
winCount = 0;
currentKbb = 0;
}
}
위의 경우처럼 생성자를 사용할 수 있다. 생성자를 위와 같이 생성한 후, Player player = new Player(name);로 생성자와 함께 객체를 선언할 수 있다.
여기서 overload를 허용하는 예시를 보여주겠다.
public class Player
{
private string name;
private int winCount;
private int currentKbb;
// Player의 생성자
public Player(string name)
{
this.name = name;
winCount = 0;
currentKbb = 0;
}
// 생성자 overloading (메소드 overloading)
public Player(string name, int winCount)
{
this.name = name;
this.winCount = winCount;
currentKbb = 0;
}
}
위와 같이, 같은 이름의 생성자라 할지라도 그 매개변수의 갯수나 자료형에 따라 다른 생성자를 호출할 수도 있는 것이다.
그리고 예시에서 느꼈듯이, this의 사용법도 예측이 가능할 것이다. this는 메소드에서 주로 많이 사용되는데, 외부에서 불러온 매개변수와 현재 클래스에 포함된 매개변수의 이름이 같을 때, 메소드 내에서는 매개변수의 우선순위가 높다. 따라서 클래스 내의 name이나 winCount라는 변수에 메소드의 매개변수 값을 적용하려고 할 때, name = name; 이라고 작성한다면 매개변수 안에 매개변수의 값을 적용하는 것이기 때문에 쓸모없는 코드가 된다. 따라서 this.name = name; 이라고 작성해야 현재 클래스 내의 변수에 매개변수의 값이 적용되는 바람직한 코드인 것이다.
마지막으로 설명할 부분은 디폴트 매개변수를 이용한 메소드 오버로드의 예시이다.
public class Player
{
private string name;
private int winCount;
private int currentKbb;
// Player의 생성자
public Player(string name)
{
this.name = name;
winCount = 0;
currentKbb = 0;
}
// 생성자 overloading (메소드 overloading)
public Player(string name, int winCount)
{
this.name = name;
this.winCount = winCount;
currentKbb = 0;
}
// 메소드 디폴트 매개변수를 이용한 메소드 오버로드 예
// * 디폴트 매개변수는 반드시 오른쪽에서 왼쪽으로 설정이 가능함
// 위 두 생성자를 합하여 사용할 수 있음
public Player(string name, int winCount = 0)
{
this.name = name;
this.winCount = winCount;
currentKbb = 0;
}
}
맨 아래의 생성자 메소드를 보면, int winCount = 0 매개변수 부분이 변화가 있는 것을 확인할 수 있다. 이것은 디폴트 매개변수라는 것인데, 위의 두 메소드를 합한 것으로 알면 된다. 때에 따라 name 매개변수만 적용하여 메소드를 호출하면 winCount는 0으로 자동 초기화되고, winCount까지 따로 적용하여 메소드를 호출하면 적용한 winCount까지 전달되는 것이다.
또한 Property는 무엇일까? Property를 알기 전에, 우리는 private와 public의 필요성에 대해 알아야 할 필요가 있다. 먼저 public은 모두가 알다시피 클래스 내부만 사용하지 않고 외부에서도 접근이 가능하게 객체나 변수를 선언할 때 쓰인다. 하지만 private의 용법이나 필요성에 대해 헷갈리는 분이 많은데, 왜 private를 사용해야 할까?
먼저, 간단한 코드를 살펴보자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.VirtualTexturing;
public class Character
{
// 캐릭터 이름
private string name;
// 캐릭터 체력
public int hp;
// 캐릭터 이동속도
private int speed;
// 캐릭터 클래스 생성자
public Character(string name, int hp, int speed)
{
this.name = name;
this.Hp = hp;
this.speed = speed;
}
// 캐릭터 정보 출력
public void ShowInfo()
{
Debug.Log("캐릭터 이름 : " + name);
Debug.Log("캐릭터 체력 : " + Hp);
Debug.Log("캐릭터 이동속도 : " + speed);
}
}
public class PropertyComponent : MonoBehaviour
{
void Start()
{
Character player1 = new Character("불꽃전사",200, 20);
player1.ShowInfo();
Character player2 = new Character("꽃미남도적", 80, 40);
player2.ShowInfo();
Debug.Log("플레이어1이 보스로부터 타격을 받았습니다.");
player1.Hp = -300;
player1.ShowInfo();
}
}
간단한 코드이다. Character 클래스에 Character의 기본 정보를 저장하고, 기본 정보를 출력할 수 있는 ShowInfo 메소드를 작성하였다. 이후, PropertyComponent 클래스에서 게임이 실행되는데, Debug 부분을 보면 플레이어1이 보스로부터 타격을 받았다는 상황이 부여되었다. 이후 간단하게 객체로 선언한 player1의 public 변수인 hp에 접근하여 보스의 피해량을 감안해 hp를 -300으로 적용했다. 이 때의 문제점은, 유저의 UI에는 나의 hp가 -300으로 보일 것인데 이게 오류이다. 일반적으로 유저의 hp는 0이 하한이라고 모두들 인지하고 있는데, 이런 부분에서 이질감을 느낄 수 있다는 것이다.
무분별한 기본 정보 접근을 막기 위해 private를 사용하고, 접근하거나 수정하는 방법은 메소드를 활용한다는 것을 알 필요가 있다. 아래는 수정된 코드이다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.VirtualTexturing;
public class Character
{
// 캐릭터 이름
private string name;
// 캐릭터 체력
private int hp;
// 캐릭터 이동속도
private int speed;
// 캐릭터 클래스 생성자
public Character(string name, int hp, int speed)
{
this.name = name;
this.Hp = hp;
this.speed = speed;
}
public void SetHp(int hp)
{
if(hp < 0)
{
this.Hp = 0;
return;
}
this.Hp = hp;
}
public int GetHp()
{
return hp;
}
// 캐릭터 정보 출력
public void ShowInfo()
{
Debug.Log("캐릭터 이름 : " + name);
Debug.Log("캐릭터 체력 : " + Hp);
Debug.Log("캐릭터 이동속도 : " + speed);
}
}
public class PropertyComponent : MonoBehaviour
{
void Start()
{
Character player1 = new Character("불꽃전사",200, 20);
player1.ShowInfo();
Character player2 = new Character("꽃미남도적", 80, 40);
player2.ShowInfo();
Debug.Log("플레이어1이 보스로부터 타격을 받았습니다.");
player1.SetHp(-300);
player1.ShowInfo();
}
}
다음과 같이 작성하여 SetHp() 메소드로 -300 값을 적용한다면, SetHp() 메소드 내부의 조건문을 인식하여 0 아래로 내려가는 hp가 적용되더라도 하한이 0으로 적용될 것이다.
하지만 좀 더 깊이 들어가서, 이러한 GetHp와 SetHp를 좀 더 간단히 표현할 수는 없을까? 역시 구현이 되어 있다. 바로 Property라는 이름으로 구현이 되어 있다. 위 코드에서 용법을 말해주자면, 먼저 class 내부의 한 변수인 hp에 오른쪽 마우스 클릭을 하면 빠른 작업 및 리필터링에 보면 필드 캡슐화 : 'hp' ( 그리고 속성을 사용함 ) 을 확인할 수 있다. 이를 클릭해보면 public int hp { get => hp; set => hp = value; } 라는 코드가 새롭게 생성된다. 이 코드를 일단 용법을 설명하기 전 입맛에 맞게 수정해보겠다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.VirtualTexturing;
public class Character
{
// 캐릭터 이름
private string name;
// 캐릭터 체력
private int hp;
// 캐릭터 이동속도
private int speed;
// 캐릭터 클래스 생성자
public Character(string name, int hp, int speed)
{
this.name = name;
this.Hp = hp;
this.speed = speed;
}
// 프로퍼티
public int Hp {
get { return hp; } // get 프로퍼티
set { // set 프로퍼티
if (value < 0)
{
hp = 0;
return;
}
hp = value;
}
}
// 캐릭터 정보 출력
public void ShowInfo()
{
Debug.Log("캐릭터 이름 : " + name);
Debug.Log("캐릭터 체력 : " + Hp);
Debug.Log("캐릭터 이동속도 : " + speed);
}
}
일단 위와 같이 Property의 get과 set 부분을 수정하였다. 먼저 짚고 넘어가야 할 것은, 우리가 사용하는 Property는 메소드이고, get과 set도 메소드이다. 따라서 상속으로 인한 여러 기능들을 사용할 수 있다는 장점이 있다. 이 Property를 사용하면, 전의 코드엔 있었던 GetHp와 SetHp를 작성하지 않고 Property만 작성하면 GetHp와 SetHp의 두 기능을 모두 사용할 수 있다. 이제 PropertyComponent 클래스를 다시 작성해 보겠다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.VirtualTexturing;
public class PropertyComponent : MonoBehaviour
{
void Start()
{
Character player1 = new Character("불꽃전사",200, 20);
player1.ShowInfo();
Character player2 = new Character("꽃미남도적", 80, 40);
player2.ShowInfo();
Debug.Log("플레이어1이 보스로부터 타격을 받았습니다.");
// 플레이어1의 체력을 변경함 (체력 변경 메소드 실행)
player1.Hp = -300;
Debug.Log("플레이어1의 체력은 " + player1.Hp + "입니다.");
}
}
위와 같이 작성이 되었는데, 잘 보면 hp로는 접근을 못하지만 Property는 public이기 때문에 Property로 선언한 Hp로 접근하여 마치 public 변수처럼 사용한 모습을 볼 수 있다. 따라서 이 Public 변수인 Hp Property로 인해 hp가 0으로 내려갈 수 없는 제한이 있는 private한 상태이지만, 마치 public 변수처럼 사용하는 모습을 볼 수 있다.
'기록하며 노세' 카테고리의 다른 글
상속 기능을 더 응용해볼 수 있을까? (0) | 2024.02.07 |
---|---|
C#에서 상속을 알아보자. (0) | 2024.02.06 |
C#에서 메소드(Method)란? (2) | 2024.02.05 |
값 형식의 배열, 객체 참조 배열, 그리고 Instantiate (2) | 2024.02.01 |
C#에서 조건문이란? enum이 뭘까? (2) | 2024.02.01 |
- Total
- Today
- Yesterday
- 침해사고분석및대응
- base
- 상속
- 핸디커뮤니케이션즈
- 게임리뷰
- 유니티개발
- OOP
- SpaceShooter
- 유니티
- 물데네전세표응
- 코루틴
- 가위바위보게임
- C#
- 메타버스
- override
- 게임개발
- 자식클래스
- 정보보호
- sbs아카데미게임학원
- 부모클래스
- virtual
- 업캐스팅
- apstndp
- 정보보호전문가
- 정보보안
- 보안
- unity
- Abstract
- 익숙한출발
- 디폴트매개변수
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
28 | 29 | 30 |