티스토리 뷰

기록하며 노세

C#에서 메소드(Method)란?

늙어서노세 2024. 2. 5. 14:14

 우리는 보통 C언어를 학습하게 되고, 이후 심화적으로 특정 툴을 사용하기 위해 C#이나 C++ 언어를 배우기도 한다. C언어에서 자주 쓰던 함수라는 개념이 C#에서는 메소드 개념으로 바뀌었다. C#은 JAVA라는 획기적인 언어를 대적하기 위해 등장하였던 언어이기 때문에, C의 기반보단 JAVA의 기반을 더 많이 따라간 모습을 볼 수 있다.

 

 메소드란, 클래스의 멤버 데이터를 기반으로 동작, 연산, 제어 등의 실질적인 코드를 동작시키고 구성하기 위한 문법이라는 정의를 가지고 있다. C언어에서 함수를 다루었을 때와 마찬가지로, C#에서 메소드를 다룰 때도 여러 경우의 수와 고민을 하여야 한다. 이 메소드를 이용하여 구현하려는 기능이 어떤 클래스의 데이터를 기반으로 하는지, Caller와 Receiver를 어디로 설정해야 하는지 등 머리속으로 구조를 그려본 후 메소드를 작성하여야 구현할 기반을 마련할 수 있다.

 

 예를 들어, 일단 Caller와 Receiver를 고려하지 않고 버전을 반환하는 메소드를 만들어보면 아래와 같이 만들어 볼 수 있다.

public class UnityProgramInfo
{
    private string version = "2021.3";

    // 버전 정보를 출력해주는 메소드
    public void PrintVersion()
    {
        Debug.Log(version);
    }
    // 다양한 정보를 출력해주는 메소드들 ....
}

 

  위와 같이 클래스 내의 version이라는 문자열 변수를 출력해주는 PrintVersion() 메소드를 생성할 수 있다.

 

 그러면 C#에서 사용하는 메소드는 어떠한 유형과 특성이 있을까? 메소드의 유형은 크게 네 가지로 나눌 수 있다.

 

1. 특정 객체의 메소드 호출자는 데이터의 소유권이 없고 데이터의 소유권을 가진 객체의 메소드를 호출할 때

타입1 : 반환값도 없고 매개변수도 없는 메소드 유형 -> void 메소드명() { ... }

public void Hello()
{
	...
}

 

2. 특정 객체가 데이터는 가지고 있지만 데이터의 가공을 다른 객체의 메소드를 통해 수행하고자 할 때

타입2 : 반환값은 없고 매개변수는 있는 메소드 유형 -> void 메소드명(매개변수들...) { ... }

public void Hello(int val1, int val2)
{
	...
}

 

3. 데이터의 소유권을 가진 객체가 다른 객체의 메소드를 통해 데이터의 가공만을 수행하고 가공된 데이터를 받아내고자 할 때

타입3 : 반환값도 있고 매개변수도 있는 메소드 유형 -> 반환형 메소드명(매개변수들...) { ... }

public int Hello(int val1, int val2)
{
	...
    return val1 + val2;
}

 

4. 데이터의 소유권을 가진 객체의 메소드를 통해 특정 데이터의 값을 받아내고자 할 때

타입4 : 반환값은 있고 매개변수는 없는 메소드 유형 -> 반환형 메소드명() { ... return 반환값; }

public int Hello()
{
	...
    return returnValue;
}

 

위의 유형들을 응용하여 아래와 같이 다양한 메소드를 생성할 수 있다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 제시하는 데이터를 병합해서 출력해주거나 데이터를 조합가공해서 돌려주는 기능의 클래스
public class MergeString
{
    // 두 개의 정수값을 문자열로 붙여서 출력해주는 메소드
    public void PrintIntMergeString(int value1, int value2)
    {
        Debug.Log(value1.ToString() + value2.ToString());
    }
    
    // 문자열과 정수값을 문자열로 출력할 문자열로 만들어서 돌려주는 메소드
    public string GetMergeStringAndInt(string str, int value)
    {
        string returnData = str+" : " + value.ToString();
        return returnData;
    }
    // 다양한 문자열과 숫자형 데이터들을 병합 조합해서 출력 또는 돌려주는 메소드들 ....
}

// 다양한 범위의 랜덤값을 추첨하여 문자열 형식으로 돌려주는 메소드
public class RandomString
{
    // 1부터 10 사이의 랜덤한 값을 추첨하여 출력형식의 문자열을 돌려주는 메소드
    public string RandomOneToTen()
    {
        return "1~10 사이의 랜덤값 : " + Random.Range(1, 11).ToString();
    }
    // 다양한 범위의 랜덤한 값을 추첨하여 출력형식의 문자열을 돌려주는 메소드
    // 예) 100 ~ 200, 1000 ~ 10000 ....
}

public class MethodTypeComponent : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // 메소드 유형1 사례
        // -> 유니티 객체에게 버전출력을 요구할 때
        UnityProgramInfo unity = new UnityProgramInfo();
        unity.PrintVersion();

        // 메소드 유형2 사례
        // -> 문자열 조합 객체에게 두개의 숫자를 합쳐서 출력하기를 요구할 때
        MergeString mergeStr = new MergeString();
        mergeStr.PrintIntMergeString(10, 30);

        // 메소드 유형3 사례
        // -> 문자열조합 객체에게 문자열과 숫자를 조합해서 문자열로 돌려주기를 요구할 때
        string printStr = mergeStr.GetMergeStringAndInt("숫자", 10);
        Debug.Log(printStr);

        // 메소드 유형4 사례
        // -> 랜덤 문자열 객체에게 1부터 10 사이의 랜덤값을 추첨하여 문자열로 돌려주기를 요구할 때
        RandomString randomStr = new RandomString();
        string str = randomStr.RandomOneToTen();
        Debug.Log(str);
    }
}

 

 이러한 메소드의 유형을 이용하여, 강의 시간에 console로 구현할 수 있는 자그마한 가위바위보 게임을 만들어 보았다.

using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Experimental.AI;

// 역할 : 플레이어(Player), 게임(KbbGame), 게임운영자(GameOperator)

public class Player
{
    private string name; // 이름
    private int winCount; // 승리 카운트
    private int currentKbb; //가장 최근에 낸 가위바위보값

    // 승리 카운트 증가
    public void Win()
    {
        winCount++;
    }

    // 승리 카운트 반환
    public int GetWinCount()
    {
        return winCount;
    }

    // 게임에서 정해진 플레이어 이름을 설정
    public void SetName(string name) // 메소드 유형1
    {
        this.name = name;
    }

    // 플레이어의 이름을 반환
    public string GetName() // 메소드 유형4
    {
        return name;
    }

    // 유저의 가위바위보 선택 및 출력
    public int PlayKbb()
    {
        currentKbb = Random.Range(0, 3);

        // 랜덤값과 가위바위보 매칭
        string kbbName = "";
        switch(currentKbb)
        {
            case 0:
                kbbName = "가위";
                break;
            case 1:
                kbbName = "바위";
                break;
            case 2:
                kbbName = "보";
                break;
        }

        // 유저의 가위바위보 값 출력
        Debug.Log("[" + name + "] : " + kbbName);

        return currentKbb;
    }
}

// 가위바위보 게임 운영자
public class GameOperator
{
    private string name; // 운영자 이름

    public void SetName(string name) // 메소드 유형1
    {
        this.name = name;
    }

    // 가위바위보 게임 안내 메세지 출력
    public void StartKbbMessage() // 메소드 유형1
    {
        Debug.Log("[" + name + "] : 자 지금부터 가위바위보 게임을 시작합니다.");
    }

    // 가위바위보 게임 시작 메세지 출력
    public void LetGoKbbGameMessage(string player1Name, string player2Name, int gameCount) // 메소드 유형2
    {
        Debug.Log("[" + name + "] : " + player1Name + "과 " + player2Name + "는 가위바위보를 " + gameCount + "회 내주세요.");
    }

    // * 운영자가 가위바위보 게임을 판단할 때는 유저의 이름, 유저가 낸 가위바위보 값, 승리 카운트 증가 등의 값과 기능이 모두 필요하므로
    // 이런 경우에는 객체의 참조값을 전달 받는게 맞음
    public void KbbGameResult(Player player1, Player player2)
    {
        int p1Kbb = player1.PlayKbb();
        int p2Kbb = player2.PlayKbb();

        if(p1Kbb == p2Kbb) // 비김
        {
            Debug.Log("[" + name + "] : " + player1.GetName() + "와(과) " + player2.GetName() + "은(는) 비겼어요.");
        }
        // 가위 vs 보, 바위 vs 가위, 보 vs 바위
        else if ((p1Kbb == 0 && p2Kbb == 2) || (p1Kbb == 1 && p2Kbb == 0) || (p1Kbb == 2 && p2Kbb == 1))
        {
            Debug.Log("[" + name + "] : " + player1.GetName() + "이(가) " + player2.GetName() + "을(를) 이겼어요.");
            player1.Win();
        }
        else
        {
            Debug.Log("[" + name + "] : " + player1.GetName() + "이(가) " + player2.GetName() + "에게 졌어요.");
            player2.Win();
        }
    }

    // * 운영자가 가위바위보 게임의 최종 결과를 선언하기 위해서는 유저이름, 유저의 승리카운트 등의 값이 모두 필요하므로
    // 이런 경우에는 플레이어 객체의 참조값을 전달받는게 맞음
    public void EndKbbMessage(Player player1, Player player2)
    {
        Debug.Log("[" + name + "] : 이제는 가위바위보 게임을 종료합니다.");

        if (player1.GetWinCount() > player1.GetWinCount())
            Debug.Log("[" + name + "] : 최종 승리자는 " + player1.GetName() + "입니다.");
        else if (player2.GetWinCount() > player1.GetWinCount())
            Debug.Log("[" + name + "] : 최종 승리자는 " + player2.GetName() + "입니다.");
        else
            Debug.Log("[" + name + "] : 두 플레이어는 비겼습니다.");
    }
}

public class KbbGame : MonoBehaviour
{
    public string operatorName; // 운영자 이름
    public string player1Name; // 플레이어1 이름
    public string player2Name; // 플레이어2 이름
    public int gameCount; // 게임 획수

    // Start is called before the first frame update
    void Start()
    {
        GameOperator gameOperator = new GameOperator();
        gameOperator.SetName(operatorName);
        // 유저1 객체 생성
        Player player1 = new Player();
        // 플레이어1이 게임에서 정해준 이름을 설정함
        player1.SetName(player1Name);
        // 유저2 객체 생성
        Player player2 = new Player();
        // 플레이어2가 게임에서 정해준 이름을 설정함
        player2.SetName(player2Name);


        // 게임운영자가 가위바위보 게임 안내메세지 출력(Operator)
        gameOperator.StartKbbMessage(); // 메소드 유형1

        // 게임운영자가 가위바위보 시작 안내메세지 출력(Operator)
        gameOperator.LetGoKbbGameMessage(player1.GetName(), player2.GetName(), gameCount); // 메소드 유형2

        ////유저들이 가위바위보를 냄
        //int pkbb1 = player1.PlayKbb(); // 플레이어1의 가위바위보 값을 돌려받아 저장
        //int pkbb2 = player2.PlayKbb(); // 플레이어2의 가위바위보 값을 돌려받아 저장
        //gameOperator.KbbGameResult(pkbb1, pkbb2);

        // 게임운영자가 플레이어들이 가위바위보를 내고 해당 가위바위보 값을 기준으로 게임운영자가 결과를 판정함
        gameOperator.KbbGameResult(player1, player2); // 메소드 유형2

        // 지정한 게임 횟수만큼 게임을 실행함
        for(int i=0;i<gameCount;i++)
        {
            // 게임운영자가 플레이어들이 가위바위보를 내고 해당 가위바위보 값을 기준으로 게임운영자가 결과를 판정함
            gameOperator.KbbGameResult(player1, player2); // 메소드 유형2
        }

        // 게임운영자가 게임의 최종 승리자 판단
        gameOperator.EndKbbMessage(player1, player2); // 메소드 유형2

        // 최종 게임 결과 출력
        FinalGameInfo(operatorName, player1, player2); // 메소드 유형2
    }

    // 게임 종료 후 게임 분석 결과 데이터를 출력함
    public void FinalGameInfo(string operatorName, Player player1, Player player2)
    {
        Debug.Log("[게임 최종 결과 데이터]");
        Debug.Log("-------------------------------------------------");
        Debug.Log("게임 참가자 : " + operatorName + ", " + player1.GetName() + ", " + player2.GetName());
        Debug.Log("-------------------------------------------------");
        Debug.Log(player1.GetName() + "승리 횟수 : " + player1.GetWinCount());
        Debug.Log(player2.GetName() + "승리 횟수 : " + player2.GetWinCount());
        Debug.Log("-------------------------------------------------");
    }
}

 

아직 생성자와 상속 등의 핵심 내용들은 완벽히 학습하지 않아 적용하지 못했지만, 추후 학습하면 보다 간략하게 구현할 수 있을 것으로 보인다.