Unity Chapter 7-2. C# 프로그래밍 [중급] (2/2) : 상속

Date:     Updated:

카테고리:

태그:

인프런에 있는 이제민님의 레트로의 유니티 C# 게임 프로그래밍 에센스 강의를 듣고 정리한 필기입니다. 😀
🌜 [레트로의 유니티 C# 게임 프로그래밍 에센스] 강의 들으러 가기!


Chapter 7. C# 프로그래밍 : 중급 (2/2)


🔔 상속

상속이란?

베이스가 되는 클래스(부모)가져와서 그 위에 나만의 클래스를 확장해서 만드는 것.

  • A 클래스를 B, C, D 클래스가 상속 받는다면 B, C, D는 A의 기능들을 공통적으로 가지고 있게 된다.
  • 어떤 공통적인 기능들은 부모클래스로 추상화해놓고 이를 여러 자식 클래스에서 상속받아 자신 만의 기능들을 추가로 덧붙이는 방식


상속과 다형성의 장점

  • 코드를 재활용 할 수 있다.
  • 구조를 간결하게 할 수 있다.


부모클래스 상속받는 방법 & MonoBehaviour

  • 클래스 이름 뒤에 : 콜론과 함께 파생할 부모클래스의 이름을 써주면 된다.

  • MonoBehaviour

    • 유니티에서 C# 스크립트를 만들 때 기본으로 붙는 부모클래스
      • MonoBehaviour이 가지고 있는 기능들을 기반으로 하여 본인만의 기능들을 쌓아올린다.
    • 모든 컴포넌트들이 기본으로 가지는 기능들을 담고 있다.
      • 오브젝트에 붙을 수 있다던지 유니티 엔진과 메세지를 주고 받는다던지 (ex. void Update, Start함수) 등등 모든 유니티의 컴포넌트들이 가지는 기본 기능
    • c# 스크립트는 MonoBehaviour를 상속 받아야지만 MonoBehaviour의 편의 기능들을 가질 수 있다.
      • 예를 들면 스크립트를 컴포넌트로서 오브젝트에 붙일 수 있고 유니티 엔진과 메세지 기반의 상호작용을 할 수 있는 등등

📜Animal.h

📜 class Animal : 동물이 가지는 기초적이고 공통적인 데이터와 기능들이 들어가야 한다. ex) name, weight, age, 몸무게와 나이가 늘어나면 속도가 줄어드는 기능 등등

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

public class Animal
{
    public string name;
    public float weight;
    public int age;

    public void Print() 
    {
        Debug.Log(name + "| 몸무게: " + weight + "| 나이 " + age);
    }

    public float GetSpeed() 
    {
        float speed = 100f / (weight * age);

        return speed;
    }
}

public class Dog : Animal 
{
    public void Hunt()
    {
        float speed = GetSpeed();  // 사용가능
        Debug.Log(speed + " 의 속도로 달려가서 사냥했다.");

        weight = weight + 10f;
        Debug.Log("사냥 후 몸무게가 늘어 " + weight + "몸무게가 되었다."); 
    }
}

// 샌드박스 디자인패턴 : 미리 필요한 기능들은 미리 부모클래스에 싹다 모아놓고 자식클래스에서 마구잡이로 그것들을 조합해서 자신만의 기능을 만드는 것

public class Cat: Animal
{
    public void Stealth()
    {
        Debug.Log("숨었다");
    }
}
  • MonoBehaviour는 상속받지 않게 : MonoBehaviour 은 지워주었다.
    • 이제 📜Animal.h 는 다른 오브젝트에 붙일 수 없고 우리가 사용해 온 그 Update(), Start(), OnTriggerEnter() 같은 이벤트 함수들을 사용할 수 없게 된다.
  • class Animal
    • Animal의 데이터(멤버변수)
      • name
      • weight
      • age
    • Animal의 기능(멤버함수)
      • public void Print()
        • Animal 객체의 데이터(멤버변수)들을 출력해준다.
      • public float GetSpeed()
        • 속도를 리턴
        • 몸무게와 나이가 늘어날 수록 속도는 줄어든다.
  • class Dog
    • Animal 클래스를 상속받는다.
      • Animal의 데이터와 기능들을 모두 그대로 물려 받아 사용할 수 있다.
      • Animal로부터 물려 받은 데이터와 기능들과 함께 Dog 만이 가지는 기능을 확장할 수 있다.
    • Dog의 데이터(멤버변수)
      • name (Animal로부터 물려받음)
      • weight (Animal로부터 물려받음)
      • age (Animal로부터 물려받음)
    • Dog의 기능(멤버함수)
      • public void Print()
        • (Animal로부터 물려받음)
      • public float GetSpeed()
        • (Animal로부터 물려받음)
      • 🖐 public void Hunt()
        • Dog만이 가지는 기능이다.
        • 사냥 기능 : 속도를 출력하고 몸무게를 늘리고 출력함
        • Animal 로부터 물려받은 GetSpeed()와 weight을 사용할 수 있다.
  • class Cat
    • Animal 클래스를 상속받는다.
      • Animal의 데이터와 기능들을 모두 그대로 물려 받아 사용할 수 있다.
      • Animal로부터 물려 받은 데이터와 기능들과 함께 Cat 만이 가지는 기능을 확장할 수 있다.
    • Cat의 데이터(멤버변수)
      • name (Animal로부터 물려받음)
      • weight (Animal로부터 물려받음)
      • age (Animal로부터 물려받음)
    • Cat의 기능(멤버함수)
      • public void Print()
        • (Animal로부터 물려받음)
      • public float GetSpeed()
        • (Animal로부터 물려받음)
      • 🖐 public void Stealth()
        • Cat만이 가지는 기능이다.
        • 숨는 기능


📜Test.h

  • 빈 오브젝트에 📜Test.h를 붙이고 유니티에서 실행해보자
    • 📜Animal.h 는 현재 MonoBehaviour를 상속받지 않아 다른 오브젝트에 붙일 수 없음
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    void Update()
    {
        Cat nate = new Cat(); // 고양이 객체
        nate.name = "Nate";
        nate.weight = 1.5f;
        nate.age = 3;

        Dog jack = new Dog(); // 강아지 객체
        jack.name = "Jack";
        jack.weight = 5f;
        jack.age = 2;

        nate.Stealth();
        nate.Print();  // 부모인 Animal로부터 물려받은 기능 

        jack.Hunt();
        jack.Print();  // 부모인 Animal로부터 물려받은 기능 
    }
}


cf. 샌드박스 디자인 패턴

샌드박스 : 필요한 기능들은 미리 부모클래스에 싹다 모아놓고 자식클래스에서 마구잡이로 그것들을 조합해서 자신만의 기능을 만드는 디자인 패턴


접근 지정자 public, private, protected

  • public이 붙은 멤버 변수와 멤버 함수는 자식이든 외부에서든 접근이 가능하다.
  • private이 붙은 멤버 변수와 멤버 함수는 외부는 물론이고 자식 클래스에서도 접근이 불가능하다.
    • 상속시 자식에게 물려주기 싫은 멤버들은 private으로 하는 것이 좋다.
  • protected가 붙은 멤버 변수와 멤버 함수는 외부에서는 접근이 불가능하지만 자식 클래스 내에서는 접근이 가능하다.
    • 상속시 자식이 접근할 수 있게 그대로 물려주고 싶긴 하지만 외부에선 접근 못하게 하고 싶은 멤버들은 protected으로 하는 것이 좋다.
    • 외부에서 접근을 못하게 한다는 것은 객체로 접근하는 것도 포함이다.
      • 부모클래스의 멤버 함수인 A()는
        • 잘 물려주어 자식 클래스 내에서는 물려받은 멤버 함수로서 접근, 사용이 가능하지만
        • 부모 클래스로 부모타입 객체를 생성하여 객체를 통해 접근하려 할 때는 접근이 불가능하다.
      public class Parent
      {
          protected int A()  // Parent 클래스의 A() 멤버 함수는 protected 이다.
          {
              return 1;
          }
      }
      
      public class Child : Parent
      {
          public void B()
          {
              A();  // 자식인 Child에서 상속되었는데 protected이므로 접근 및 사용 가능.
      
              Parent p;
              p.A(); // 에러! ⚡ 다만 외부에서는 사용 불가능. 
          }
      }
      

접근 지정자를 사용하는 이유

코드를 바깥에서 봤을 때 적절히 숨겨놓으면 간결해지기 때문. 성능과는 거리가 멀고 단지 인간적인 개념에서 사용한다.



🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기


Unity Lesson 1 카테고리 내 다른 글 보러가기

댓글 남기기