- 문제
인벤토리에서 장착한 아이템의 속성값을 플레이어 정보창 내 속성값에 (+x) 으로 출력하려고 하려고 한다.
공격력: 10 (+7)
방어력: 10 (+5)
구현하려고 했던 방식은 다음과 같다.
public class Inventory
{
public int attackIncrease = 0;
public int defenseIncrease = 0;
// 필드에 공격력/방어력 증가값 변수를 0으로 최초 선언
public static void ManageEquipment()
{
// 새 아이템 장착
Player.attackPower += selectedItem.attackPower;
Player.defense += selectedItem.defense;
Inventory inventory = new Inventory();
inventory.attackIncrease = selectedItem.attackPower;
inventory.defenseIncrease = selectedItem.defense;
// Inventory를 동적 변수로 생성
selectedItem.isEquipped = true;
equippedItem = selectedItem;
Console.WriteLine($"{selectedItem.name}을(를) 장착했습니다.");
ManageEquipment();
}
인벤토리 클래스에서 Inventory 동적 변수를 생성해 장착한 아이템의 공격력과 방어력을 필드에서 선언한 변수에 저장하고,
public class Player
{
public static void ShowStatus(Inventory inventory)
{
Console.WriteLine("\n===== 상태창 =====");
Console.WriteLine($"이름: {playerName}");
Console.WriteLine($"레벨: {playerLv}");
Console.WriteLine($"직업: {playerJob}");
int attackDifference = Inventory.attackIncrease;
int defenseDifference = Inventory.defenseIncrease;
if (attackDifference > 0)
{
Console.WriteLine($"공격력: {Player.attackPower} (+{attackDifference})");
}
else
{
Console.WriteLine($"공격력: {Player.attackPower}");
}
if (defenseDifference > 0)
{
Console.WriteLine($"방어력: {Player.defense} (+{defenseDifference})");
}
else
{
Console.WriteLine($"방어력: {Player.defense}");
}
Console.WriteLine($"체력: {hp}");
Console.WriteLine($"Gold: {playergold}G");
Console.WriteLine("===================\n");
플레이어 클래스에서 인벤토리 클래스의 Inventory 동적 변수를 받아와 공격력/방어력에 출력한다.
- 변수(new 인스턴스 생성) 의도
다른 클래스의 필드나 변수는 단순히 public 으로 선언한다고 해서 사용할 수 없다.
public 필드는 상점에서 파는 물건이다.
'팔겠다'고 선언만 해둔 것이지 상점이 없으면 그 물건은 사용할 수 없다.
이때, new 키워드로 접근하면 상점을 만들 수 있게 된다.
- Static이 아닌 필드, 메서드 또는 속성 " "에 개체 참조가 필요합니다.
int attackDifference = Inventory.attackIncrease;
int defenseDifference = Inventory.defenseIncrease;
하지만 이렇게 진행했을 때 위의 두 변수에서 개체 참조가 필요하다는 오류가 발생한다.
- 원인
클래스와 변수에 대한 개념이 부족해 코드에 문제가 많지만,
Static 메소드 안에서 Static이 아닌 변수를 사용한 것이 원인이었다.
Q. 다른 클래스의 필드나 변수를 가져오기 위해서 인스턴스를 생성해야 하는 게 아니었나?
이를 이해하기 위해선 스테틱(Static)에 대한 개념 정립이 필요하다.
각 스크립트는 독립적으로 존재한다.
하지만 스테틱(Static) 키워드를 사용하면 해당 필드, 메서드, 속성 등이 프로그램 실행 시점부터 메모리에 저장되고, 별도의 인스턴트를 만들지 않고도 접근할 수 있다.
프로그램 실행 시점부터 상점이 없어도 물건을 팔 수 있게 되는 것이다.
- 변수(인스턴스 변수)는 static 메서드 내에서 직접 사용할 수 없다.
Q. 그래서 static 메서드에 왜 동적 변수를 넣을 수 없는 걸까?
static은 상점이 없어도 물건을 팔 수 있는 대신 이 물건을 계속 가지고 있어야 된다는 단점을 가지고 있다.
정해진 물건들로만 거래해야 한다는 의미이다.
내가 썼던 상태창 오류 코드로 자세히 살펴보자.
public class Player
{
public static void ShowStatus(Inventory inventory)
{
Console.WriteLine("\n===== 상태창 =====");
Console.WriteLine($"이름: {playerName}");
Console.WriteLine($"레벨: {playerLv}");
Console.WriteLine($"직업: {playerJob}");
int attackDifference = Inventory.attackIncrease;
int defenseDifference = Inventory.defenseIncrease;
if (attackDifference > 0)
{
Console.WriteLine($"공격력: {Player.attackPower} (+{attackDifference})");
}
else
{
Console.WriteLine($"공격력: {Player.attackPower}");
}
if (defenseDifference > 0)
{
Console.WriteLine($"방어력: {Player.defense} (+{defenseDifference})");
}
else
{
Console.WriteLine($"방어력: {Player.defense}");
}
Console.WriteLine($"체력: {hp}");
Console.WriteLine($"Gold: {playergold}G");
Console.WriteLine("===================\n");
'상태창'이라는 공간은 상점 없이도 '항상 정해진 물건들(이름, 레벨, 직업, 체력, 골드)'을 팔 수 있다.
각 물건(객체)을 프로그램 종료까지 가져가야 한다.
하지만 여기서 변수(공격력 증가, 방어력 증가)라는 새로운 물건이 추가되면서 규칙을 깨버렸기 때문에,
'상태창' 상점에(static 메서드) 혼란이 발생하게 되는 것이다.
- 해결
public static int attackIncrease = 0;
public static int defenseIncrease = 0;
static 변수로 변경해 모든 클래스에서 접근할 수 있도록 한 다음,
if (Inventory.attackIncrease > 0)
{
Console.WriteLine($"공격력: {Player.attackPower} (+{Inventory.attackIncrease})");
}
else
{
Console.WriteLine($"공격력: {Player.attackPower}");
}
if (Inventory.defenseIncrease > 0)
{
Console.WriteLine($"방어력: {Player.defense} (+{Inventory.defenseIncrease})");
}
else
{
Console.WriteLine($"방어력: {Player.defense}");
}
상태창에 해당 static 변수를 불러와 사용했다.
해결은 쉬웠지만 좋은 코드는 아니다.
정적 변수는 프로그램 종료까지 가지고 있어야 해서 규칙을 깨기가 어렵고, 메소드가 무거워진다.
정적이 아닌 동적 메소드로 바꾸는 게 더 좋은 해결 방안이었을 것이라고 생각된다.
'[내배캠] 본 캠프 개발 학습 > 자세히 살펴보는 Q&A' 카테고리의 다른 글
유니티(Unity) 2D 맵에서 캐릭터 움직임이 끼는 현상 해결하기 (8) | 2024.10.11 |
---|---|
C# 동적 인스턴스 생성 (8) | 2024.10.01 |
C# for 문으로 상점 만들기 (4) | 2024.09.25 |
C# 문자열 보간, $ (0) | 2024.09.24 |
C# 큰따옴표와 작은따옴표의 사용 (0) | 2024.09.20 |