ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Unity]유니티 입문하기 6-11(다형성)
    프로그래밍 2023. 8. 22. 20:05

    이전 글에서는 클래스의 상속에서 이어지는 클래스의 형변환과, 오류 없는 형변환을 위해 as와 is 연산자를 사용하는 법을 배웠습니다.

    이번 글에서는 객체 지향의 마지막 특성, 다형성에 대해서 알아보겠습니다.


    다형성은 이름 그대로 해석하면 여러 가지 형태를 가지는 성질입니다.

    즉, 같은 이름의 코드가 여러가지 형태를 띠고 다양한 역할을 할 수 있음을 의미하죠.

    메서드 오버라이드메서드 오버로드를 통해 자세히 알아봅시다.

     

    메서드 오버라이드

    메서드 오버라이드는 부모 클래스의 메서드를 자식 클래스에서 재정의하는 것을 의미합니다.

    메서드 오버라이드는 아래와 같은 형태로 이루어집니다.

    접근 제한자 virtual 반환타입 메서드 이름(매개변수) //부모 클래스의 메서드
    {
    
    }
    
    접근 제한자 override 반환타입 메서드 이름(매개변수) //자식 클래스의 메서드
    {
    
    }

    이때 두 메서드는 본문의 내용은 달라도 상관 없지만, 같은 접근 제한자, 반환 타입, 이름, 매개변수를 가져야 합니다.

    즉, 같은 형태를 가지고 다른 역할을 하게 만드는 겁니다.

     

    메서드 오버라이드가 어떤 형태로 작동하는지 알아보기 위해서,

    1. 부모 클래스 타입 변수에 부모 클래스 타입 객체를 담는 경우
    2. 자식 클래스 타입 변수에 자식 클래스 타입 객체를 담는 경우
    3. 부모 클래스 타입 변수에 자식 클래스 타입 객체를 담는 경우

    위 3가지 경우로 나누어서 예시 코드를 확인해보겠습니다.

    public virtual void Walk(){ //Human 클래스
      	Debug.Log("walk");
    }
    
    public override void Walk(){ //Baby 클래스
        Debug.Log("crawl");
    }
    
    void Start() {				//PlayerController 클래스
        Human sujin = new Human("sujin", 12, 147);
        Baby jake = new Baby("jake", 3, 62);
        Human chris = new Baby("chris", 6, 110);
    
        sujin.Walk();
        jake.Walk();
        chris.Walk();
    }

    이렇게 각자의 클래스에 해당하는 코드를 넣고 나서 작동시켜 보면 아래와 같은 결과가 나오는 걸 확인할 수 있습니다.

    부모 변수에 부모 객체를 담는 경우나, 자식 변수에 자식 객체를 담는 경우는 직관적으로 이해가 가지만,

    부모 변수에 자식 객체를 담는 경우에 오버라이드 된 메서드가 작동함을 기억해 두어야겠습니다.

     

    그럼 메서드 오버라이드를 통해 재정의 하는 것이 아니라 완전히 새 메서드로 정의하려면 어떻게 해야 할까요?

    new

    메서드를 재정의 하는 것이 아니라 완전히 별개의 메서드로 새로 정의하려면 new 키워드를 사용하면 됩니다.

     

    위의 코드에서 override를 new로 바꾼 뒤 다시 실행해 보면 놀랍게도 사뭇 다른 결과가 나옵니다.

    new 키워드를 써서 메서드를 정의하게 되면, 완전히 별개의 메서드로 인식되어 객체가 Human 타입 변수에 담겨있을 때에는 Human.Wakl() 메서드가 작동되는 것을 확인할 수 있습니다.

     

    메서드 오버로드

    메서드 오버로드는 객체지향의 다형성의 또 다른 예시입니다.

    메서드 오버라이드가 부모 클래스의 변수를 자식 클래스에서 재정의 하는 것이라면,

    메서드 오버로드는 같은 클래스 내에서 식별자가 같지만 매개변수가 다른 여러 개의 메서드를 정의하는 것입니다.

     

    바로 예제 코드를 작성하고 실행해 봅시다.

    public void Eat(){ //Human 클래스
        Debug.Log("eat");
    }
    public void Eat(string food){
        Debug.Log("eat " + food);
    }
    
    
    void Start() { //PlayerController 클래스
        Human sujin = new Human("sujin", 12, 147);
    
        sujin.Eat();
        sujin.Eat("Rice");
    }

     

    위와 같이, 매개변수를 입력하지 않으면 원래 있던 메서드가, 매개변수를 입력하면 오버로드를 이용해 추가로 정의한 메서드가 작동함을 확인할 수 있습니다.

    즉, 메서드 오버로드는 이름만 같은 여러 개의 메서드를 만드는 것입니다.

     

    그럼 메서드 오버로드를 통해 메서드의 이름을 같게 할 수 있는 것이 유용한 이유는 무엇일까요?

    인수로 입력받은 두 값을 합한 값을 반환하는 Add() 메서드를 메서드 오버로드를 이용해 만들면서 알아봅시다.

    먼저, 기본적인 Add() 메서드는 다음과 같을 것입니다.

    public int Add(int a, int b){
    	return a + b;
    }

    그런데 만약, 입력값을 int로 한정하는 것이 아니라 float나 double 같은 타입의 변수도 입력받을 필요가 있다면 어떻게 해야 할까요?

     

    일단 메서드 오버로드 없이 이를 구현하고자 한다면 아래와 같이 코드를 작성할 수 있을 것입니다.

    public int AddInt(int a, int b){
    	return a + b;
    }
    
    public float AddFloat(float a, float b){
    	return a + b;
    }
    
    public double AddDouble(double a, double b){
    	return a + b;
    }

    위 함수들은 완전히 같은 구조를 가지고 완전히 같은 역할을 하지만, 매개변수의 타입이 다르다는 것 때문에 각자 다른 이름을 가지게 되었고, 이를 사용하는 입장에서도 인수의 타입에 따라 세 메서드를 구분해 가며 써야 하는 불편함이 생깁니다.

     

    하지만, 메서드 오버로드를 이용하게 되면 이야기가 달라집니다.

    public int Add(int a, int b){
    	return a + b;
    }
    
    public float Add(float a, float b){
    	return a + b;
    }
    
    public double Add(double a, double b){
    	return a + b;
    }

    위와 같이 메서드 오버로드를 이용해 Add 메서드를 여러 개 만들게 되면, 사용자가 굳이 매개변수의 타입을 구분할 필요 없이 인수의 타입에 따라서 시스템이 자동으로 해당하는 메서드를 골라서 실행시키게 됩니다.

     

    우리가 예제를 위해 계속 이용하고 있었던 Debug.Log() 메서드 또한, 이러한 메서드 오버로드 기능을 이용해 정수, 소수, 문자열 등 다양한 인수를 받을 수 있었던 것입니다.

Designed by Tistory.