[Unity C#] 메소드 -2

YongSeok·2022년 7월 10일
0

✏️ 값에 의한 전달 (Call By Value)

  • Awake() 메소드의 a,b 값을 Add() 메소드의 매개 변수로 넘긴다면
  • 넘겨지는 매개 변수 a,b는 Add() 메소드 안으로 들어가는 것일까??
private void Awake()
{
	int a = 3
    int b = 4;
    Add(a,b)
}

public void Add(int num1, int num2)
{
	int result = num1 + num2;
    Debug.Log($"{num1} + {num2} = {result}");
}

☝ num1은 a의 값과 동일한 데이터를 가지고 있지만, 별개의 메모리 공간 사용
(num1을 수정해도 a의 데이터는 변하지 않는다)


👇 CaLL By Value 예시 코드

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

public class Test : MonoBehaviour
{
    // 값에 의한 전달
    private void Awake()
    {
        int a = 3;
        int b = 4;
        Debug.Log($"Before a={a}, b={b}");
        Swap(a, b);
        Debug.Log($"After a={a}, b={b}");
    }
    public void Swap(int num1, int num2)
    {
        int temp = num1;
        num1 = num2;
        num2 = temp;
    }
    // 값은 그대로 전달하였지만 다른 메모리 공간을 사용하고 있기 때문에
    // 매개변수 num1과 num2에 무슨짓을 하더라도 a 와 b의 값에는 아무런 영향이 없다
}

✏️ 참조에 의한 전달 (Call By Reference)

  • 값에 의한 전달처럼 매개 변수가 변수나 상수로부터 값을 복사하는 것이 아닌 원본 변수를 직접 참조하는 방식
  • 원본 변소를 참조 중이기 때문에 매게 변수를 수정하면 원본이 수정된다
  • 사용방법 : 메소드의 정의와 호출에서 매개 변수 앞에 ref 키워드 사용

    👇 CaLL By Value 예시 코드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    // 참조에 의한 전달
    private void Awake()
    {
        int a = 3;
        int b = 4;
        Debug.Log($"Before a={a}, b={b}");
        Swap(ref a, ref b);
        Debug.Log($"After a={a}, b={b}");
    }
    public void Swap(ref int num1, ref int num2)
    {
        int temp = num1;
        num1 = num2;
        num2 = temp;
    }
    // ref 키워드를 붙이면 참조에 의한 전달로 판단하고,
    // 매개변수 num1에 a의 주소 값을
    // num2에 b의 주소 값을 전달해서 메모리 공간을 공유한다
    // 즉, num1의 값이 바뀌면 a도 같이 바뀐다
}

✏️ 출력 전용 매개 변수 out

  • return은 하나의 결과만 반환하는 것이 가능하다
  • 2개 이상의 결과를 반활 할 때는
  • 변경된 값이 유지되니까 ref 키워드를 사용할까?

👇 out 키워드 예시 코드

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

public class Test : MonoBehaviour
{
    private void Awake()
    {
        int a = 5;
        int b = 4;
        int result1 = 0;
        int result2 = 0;
        Divide(a, b, out result1, out result2);

        Debug.Log($"몫 = {result1}, 나머지 = {result2}");
    }
    public void Divide(int num1, int num2, out int result1, out int result2)
    {
        result1 = num1 / num2;
        result2 = num1 % num2;
    }
    // ref 매개 변수는 메소드 내부에서 결과를 저장하지 않아도 컴파일러가 아무런 경고도 하지 않는 반면,
    // out 매개 변수는 메소드 내부에서 결과를 저장하지 않은면 컴파일 에러가 발생 (개발자의 실수를 줄여준다)
}
  • ref 키워드를 사용해도 작동은 하지만 출력 전용 매개변수인 out 을 사용하는 것을 권장한다

✏️ 메소드 오버로딩

  • 두 수를 더하는 Add() 메소드를 구현하는 경우
  • 더하는 데이터 타입이 정수일 수도 있고, 실수일 수도 있다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    private void Awake()
    {
        AddInt(10, 20);
        AddFloat(0.1f, 0.2f);
    }
    public void AddInt(int num1, int num2)
    {
        int result = num1 + num2;
        Debug.Log($"{num1} + {num2} = {result}");
    }
    public void AddFloat(float num1, float num2)
    {
        float result = num1 + num2;
        Debug.Log($"{num1} + {num2} = {result}");
    }
}

☝ 이런 식으로 필요해따라 함수를 만들수도 있지만 오버로딩 을 사용하면 더욱 깔끔하게 코딩을 할 수 있다

  • 오버로딩이란 동일한 메소드 이름으로 여러 종류의 메소드를 구현하는것
  • 매개 변수의 개수와 형식을 분석하여 메소드를 선택
    • 반환 형식은 고려하지 않기 때문에 반환 형식만 다를 경우는 구분하지 못한다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    private void Awake()
    {
        Add(10, 20);
        Add(0.1f, 0.2f);
    }
    public void Add(int num1, int num2)
    {
        int result = num1 + num2;
        Debug.Log($"{num1} + {num2} = {result}");
    }
    public void Add(float num1, float num2)
    {
        float result = num1 + num2;
        Debug.Log($"{num1} + {num2} = {result}");
    }
}

✏️ 가변 길이 매개 변수 params

  • 개수가 유연하게 변할 수 있는 매개 변수
  • 변수의 길이가 다른 메소드가 아주 많이 필요한 경우 사용
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    private void Awake()
    {
        Sum(1, 2);
        Sum(1, 2, 3);
        Sum(1, 2, 3, 4);
        Sum(1, 2, 3, 4, 5);
    }

    public void Sum(params int[] nums)
    {
        int sum = 0;
        for ( int i = 0; i < nums.Length; i++)
        {
            sum += nums[i];
        }
        Debug.Log($"합게 : {sum}");
    }
}
// Tip. 매개 변수의 형식은 같아야 한다

✏️ 명명된 매개 변수

  • 일반적으로 매개 변수에 데이터를 할당할 때 순서에 의거하여 할당하는 반면 순서에 상관없이 매개 변수의 이름에 근거하여 데이터를 할당하는 방법
  • 코드의 길이는 길어지지만 코드의 가독성이 높아진다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    private void Awake()
    {
        Player("김철수", 100);                 // 일반적인 매개 변수 사용 방식

        Player(ID: "김매개", health: 200);     // 명명된 매개변수 사용 방식
        Player(health: 300, ID: " 김변수");    // 명명된 매개변수 사용 방식
        // 매개변수명과 매개변수에 저장되는 데이터를 함께
        // 쓰기 떄문에 순서가 바뀌어도 인식가능하다!
    }

    public void Player(string ID, int health)
    {
        Debug.Log($"ID : {ID}, HP : {health}");
    }
}

✏️ 선택적 매개 변수

  • 매개 변수를 특정 값으로 초기화 하지 않았을 때 기본 값을 할당하는 것
    • 필요에 따라 매개 변수에 데이터를 할당하거나 할당하지 않을 때 사용
    • 선택적 매개 변수는 항상 필수 매개 변수 뒤에 와야 한다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    private void Awake()
    {
        Player("김철수");                 
        Player("김철수", 3000);
    }
    // 첫번째 Player함수 호출에서 health의 값을 입력하지 않았지만 선택적 매개 변수로
    // 1000값이 설정되어 있어서 1000으로 자동 설정된다

    public void Player(string ID, int health = 1000)
    {
        Debug.Log($"ID : {ID}, HP : {health}");
    }
}

👇 선택적 매개 변수를 사용한다면 선택적 매개변수보다 뒤에 필수 매개변수가 올 수 없다

public void Player(string ID, int health = 1000)
{
    Debug.Log($"ID : {ID}, HP : {health}");
}	// 올바른 방식


public void Player(string ID = "김철수", int health)
{
    Debug.Log($"ID : {ID}, HP : {health}");
}	// 잘못된 방식(에러)
  • 또 다른 주의점은 메소드 오버로딩과 선택적 매개변수를 섞어쓰지 않도록 주의해야한다

0개의 댓글