반응형
생성자 ( Constructor )
클래스의 인스턴스가 생성될 때 자동으로 호출되는 특별한 메서드
기본특징
생성자의 이름은 반드시 클래스 이름과 동일해야 한다
반환 타입을 지정하지 않는다 ( void도 사용하지 않음 )
접근 제한자는 보통 public을 사용한다
생성자 유형들의 사용 사례
1. 기본 생성자 ( 매개변수 없는 생성자 )
public class Player
{
// 기본 생성자
public Player()
{
// 초기화 코드
}
}
public class Item
{
private string itemName;
private int durability;
public Item()
{
itemName = "기본 아이템";
durability = 100;
}
}
사용시기
객체 생성 시 기본값으로 초기화가 필요할 때
직렬화/역직렬화가 필요한 클래스 (JSON 변환 등)
컬렉션에서 객체를 생성할 때
2. 매개변수가 있는 생성자
public class Player
{
private string name;
private int health;
// 매개변수가 있는 생성자
public Player(string playerName, int initialHealth)
{
name = playerName;
health = initialHealth;
}
}
public class Weapon
{
private string weaponName;
private int damage;
public Weapon(string name, int dmg)
{
weaponName = name;
damage = dmg;
}
}
사용시기
객체 생성 시 필수 데이터가 있을 때
객체의 초기 상태를 외부에서 지정해야 할 때
3. 생성자 오버로딩
public class Player
{
private string name;
private int health;
// 기본 생성자
public Player()
{
name = "Unknown";
health = 100;
}
// 이름만 받는 생성자
public Player(string playerName)
{
name = playerName;
health = 100;
}
// 이름과 체력을 받는 생성자
public Player(string playerName, int initialHealth)
{
name = playerName;
health = initialHealth;
}
}
public class Character
{
private string name;
private int health;
private string job;
public Character()
{
name = "Unknown";
health = 100;
job = "Novice";
}
public Character(string characterName)
{
name = characterName;
health = 100;
job = "Novice";
}
public Character(string characterName, string characterJob)
{
name = characterName;
health = 100;
job = characterJob;
}
}
사용시기
객체 생성 시 다양한 초기화 옵션을 제공할 때
선택적 매개변수가 많을 때
※ 예시
Character char1 = new Character(); // 기본 캐릭터
Character char2 = new Character("Hero"); // 이름만 지정
Character char3 = new Character("Warrior", "Knight"); // 이름과 직업 지정
4. this 키워드 사용
public class Player
{
private string name;
private int health;
private int level;
public Player(string name, int health)
{
this.name = name; // this로 멤버 변수와 매개변수 구분
this.health = health;
this.level = 1;
}
}
public class Enemy
{
private string name;
private int level;
private float health;
public Enemy(string name, int level, float health)
{
this.name = name;
this.level = level;
this.health = health;
}
}
사용시기
매개변수 이름이 필드 이름과 동일할 때
현재 인스턴스의 다른 멤버에 접근해야 할 때
※ 예시
Enemy boss = new Enemy("드래곤", 50, 1000f);
5. 생성자 체이닝
public class Player
{
private string name;
private int health;
private int level;
public Player() : this("Unknown", 100)
{
// 다른 생성자 호출
}
public Player(string name) : this(name, 100)
{
// 다른 생성자 호출
}
public Player(string name, int health)
{
this.name = name;
this.health = health;
this.level = 1;
}
}
public class PlayerCharacter
{
private string name;
private int level;
private string role;
public PlayerCharacter() : this("Player") { }
public PlayerCharacter(string name) : this(name, 1) { }
public PlayerCharacter(string name, int level) : this(name, level, "Warrior") { }
public PlayerCharacter(string name, int level, string role)
{
this.name = name;
this.level = level;
this.role = role;
}
}
사용시기
코드 중복을 피하고 싶을 때
여러 생성자가 비슷한 초기화 로직을 공유할 때
※ 예시
PlayerCharacter p1 = new PlayerCharacter(); // 모든 기본값
PlayerCharacter p2 = new PlayerCharacter("Hero"); // 이름만 지정
6. 정적 생성자
public class GameManager
{
private static List<Player> players;
// 정적 생성자
static GameManager()
{
players = new List<Player>();
// 다른 정적 초기화 코드
}
}
public class GameConstants
{
public static Dictionary<string, float> DamageMultipliers;
public static List<string> AvailableWeapons;
static GameConstants()
{
DamageMultipliers = new Dictionary<string, float>()
{
{"Critical", 2.0f},
{"Normal", 1.0f},
{"Weak", 0.5f}
};
AvailableWeapons = new List<string>()
{
"Sword",
"Bow",
"Axe"
};
}
}
사용시기
정적 데이터를 초기화할 때
프로그램 시작 시 한 번만 실행되어야 하는 초기화 작업
전역적으로 사용되는 설정이나 상수를 초기화할 때
※ 예시
// 정적 생성자는 자동으로 실행되므로 명시적 호출 불필요
float criticalMultiplier = GameConstants.DamageMultipliers["Critical"];
주 사용 목적
객체의 초기 상태 설정
필수 데이터 초기화
의존성 주입
리소스 할당
생성자 사용 시 주의사항
생성자에서는 가능한 한 간단한 초기화 작업만 수행
시간이 많이 걸리는 작업은 별도 메서드로 분리
예외 처리를 적절히 구현
순환 참조 피하기
실제 유니티에서의 활용 예시
public class Enemy : MonoBehaviour
{
private string enemyName;
private int damage;
private float moveSpeed;
// Awake는 생성자 대신 사용되는 유니티의 초기화 함수
private void Awake()
{
enemyName = "Monster";
damage = 10;
moveSpeed = 5f;
}
// 생성 후 초기화가 필요한 경우 Initialize 메서드 사용
public void Initialize(string name, int dmg, float speed)
{
enemyName = name;
damage = dmg;
moveSpeed = speed;
}
}
유니티에서 MonoBehaviour를 상속받는 클래스의 경우 일반적인 생성자 대신
Awake나 Start 함수를 사용하여 초기화를 수행함
생성자 체이닝 이라는 개념을 처음 알았다
그래서 이 부분만 조금 더 공부했다
생성자 체이닝이란?
하나의 생성자가 같은 클래스의 다른 생성자를 호출하는 것
체이닝(Chaining)은 '연쇄' 또는 '사슬처럼 이어진다'는 의미입니다.
생성자 체이닝에서는 this() 키워드를 사용해 다른 생성자를 호출하는데,
이것이 마치 사슬처럼 이어져 있다고 해서 '체이닝'이라고 부릅니다.
간단한 예시
public class Character
{
private string name;
private int level;
private int health;
// 1번 생성자
public Character(string name, int level, int health)
{
this.name = name;
this.level = level;
this.health = health;
}
// 2번 생성자는 1번 생성자를 호출
public Character(string name) : this(name, 1, 100)
{
// name만 받고, level은 1, health는 100으로 기본값 설정
}
// 3번 생성자는 2번 생성자를 호출
public Character() : this("Unknown")
{
// 모든 값을 기본값으로 설정
}
}
위 코드를 사용하는 방법
// 3번 -> 2번 -> 1번 생성자 순서로 호출됨
Character char1 = new Character(); // name="Unknown", level=1, health=100
// 2번 -> 1번 생성자 순서로 호출됨
Character char2 = new Character("Hero"); // name="Hero", level=1, health=100
// 1번 생성자만 직접 호출
생성자 체이닝이 없다면?
public class Character
{
private string name;
private int level;
private int health;
// 코드 중복이 발생
public Character()
{
name = "Unknown"; // 중복
level = 1; // 중복
health = 100; // 중복
}
public Character(string name)
{
this.name = name;
level = 1; // 중복
health = 100; // 중복
}
public Character(string name, int level, int health)
{
this.name = name;
this.level = level;
this.health = health;
}
}
중복되는것을 많이 볼 수 있다
생성자 체이닝을 시각적으로 표현한다면?
Character() -> Character(name) -> Character(name, level, health)
3번 생성자 -> 2번 생성자 -> 1번 생성자
이를 통해 코드 중복을 줄이고 더 깔끔한 초기화 로직을 만들 수 있을 것 같다
2번째 예시
public class Player
{
private string name;
private int health;
private string weapon;
private int level;
// 1. 모든 값을 받는 기본 생성자
public Player(string name, int health, string weapon, int level)
{
this.name = name;
this.health = health;
this.weapon = weapon;
this.level = level;
}
// 2. 이름만 받고 나머지는 기본값을 사용하는 생성자
public Player(string name) : this(name, 100, "기본 검", 1)
{
// 본문이 비어있음 - 모든 초기화는 this()를 통해 다른 생성자에서 처리
}
// 3. 이름과 무기만 받는 생성자
public Player(string name, string weapon) : this(name, 100, weapon, 1)
{
// 본문이 비어있음
}
}
위 코드 사용 방법
// 각각 다른 생성자를 사용하는 예시
Player player1 = new Player("용사"); // 이름만 지정
Player player2 = new Player("궁수", "활"); // 이름과 무기 지정
Player player3 = new Player("기사", 150, "대검", 5); // 모든 값 지정
체이닝을 사용 안한 방법
public class Player
{
private string name;
private int health;
private string weapon;
private int level;
// 코드가 중복되는 문제가 발생
public Player(string name)
{
this.name = name;
this.health = 100; // 중복
this.weapon = "기본 검"; // 중복
this.level = 1; // 중복
}
public Player(string name, string weapon)
{
this.name = name;
this.health = 100; // 중복
this.weapon = weapon;
this.level = 1; // 중복
}
public Player(string name, int health, string weapon, int level)
{
this.name = name;
this.health = health;
this.weapon = weapon;
this.level = level;
}
}
조금 더 복잡한 예시
public class Enemy
{
private string enemyName;
private int health;
private int damage;
private float moveSpeed;
private EnemyType type;
private List<string> dropItems;
// 1. 모든 속성을 초기화하는 주 생성자
public Enemy(string name, int health, int damage, float speed, EnemyType type, List<string> drops)
{
enemyName = name;
this.health = health;
this.damage = damage;
moveSpeed = speed;
this.type = type;
dropItems = drops ?? new List<string>();
}
// 2. 기본 드롭 아이템을 사용하는 생성자
public Enemy(string name, int health, int damage, float speed, EnemyType type)
: this(name, health, damage, speed, type, new List<string>{ "기본 포션" })
{
}
// 3. 기본 이동 속도를 사용하는 생성자
public Enemy(string name, int health, int damage, EnemyType type)
: this(name, health, damage, 5.0f, type)
{
}
// 4. 일반 몬스터용 간단한 생성자
public Enemy(string name)
: this(name, 100, 10, EnemyType.Normal)
{
}
}
public enum EnemyType
{
Normal,
Elite,
Boss
}반응형
'유니티 > 문법' 카테고리의 다른 글
| [Unity] 유니티 C#) 제네릭 (0) | 2024.11.29 |
|---|---|
| [Unity] 유니티 C#) 추상클래스와 가상메서드 (0) | 2024.11.27 |
| [Unity] 유니티 C#) ref 와 out 키워드 (0) | 2024.11.25 |
| [Unity] 유니티 C# 인터페이스 ( Interface) (1) | 2024.11.13 |
| [Unity] 유니티 C#) 자료구조 스택(Stack), 큐(Queue) (5) | 2024.11.02 |