타입

데이터 타입은 값(Value)타입과 참조(Reference)타입으로 나뉜다.

값 타입

Int, Float, Bool , struct, enum 등이 값 타입이다.
변수가 스택에 값 그대로를 할당한다.
new 없이 선언과 동시에 값을 할당할 수 있다.
값 타입은 복사를 하면 값 그 자체가 복사된다.

int a = 10;
int b = 20;
b = a;

debug.Log($"a : {a}");
debug.Log($"b : {b}");

-------------------------------
Log: 
a : 10
b : 10

참조 타입

Class, String , array 등은 참조 타입이다.
변수가 힙에 값이 있는곳의 위치를 할당한다.
참조타입을 사용하기 위해서는 New를 사용해서 초기화 후, 힙에 할당된 메모리를 스택 공간에서 참조해야한다.
참조타입은 복사를 하더라도 그 값이 복사가 되는게 아니라 그 값이 있는곳의 위치가 복사된다.

예시를 이렇게 드는게 맞는지는 모르겠다.

  a = new classTest();
        a.classInt = 10;
        b = a;
        Debug.Log($"a:{a.classInt} b:{b.classInt}");

        b.classInt = 30;

        Debug.Log($"a:{a.classInt} b:{b.classInt}");

-------------------------------
Log: 
a:10 b:10
a:30 b:30

b.classInt = 30; 부분에서
b의 값을 바꿔준게 아니라, b의 위치에 가서 그 값을 30으로 바꿔준것.
근데 그 위치는 a의 위치니까? a도 30으로 나온다..

 


박싱과 언박싱은 일종의 형변환이다.

우선 박싱과 언박싱은 지난 글 값타입, 참조타입에 이어지는 내용이다. 이 한줄은 꼭 기억하자.

값타입은 스택에, 참조타입은 힙에 저장되어있다.

Boxing(박싱)

값타입의 객체를 참조타입으로 변환하는 작업.

int exValue = 100;
object exRef = exValue;

int는 값타입이고, object는 참조타입이다.
위의 코드에서는 참조타입 exRef에 값 타입 exValue을 대입하였다.

스택영역에 있는 exValue값이 exRef로 변환되면서 , 힙영역에 object 형식으로 선언되며 복사되었다.
exRef는 스택영역에 존재하며 , boxed된 exValue의 주소값을 가지고있다.

UnBoxing(언박싱)

참조타입의 객체를 값형식으로 변환하는 작업.

int exValue = 100;
object exRef = exValue;
int exSecondValue = (int)exRef;

한번 박싱한 exRef를 다시 int타입인 exSecondValue에 넣고있다.

언박싱을 할때는 다른타입으로 하거나 해당 타입보다 작은 범위로 변환을 할때는 오류가 발생한다.
그래서 is 연산자를 이용해서 미리 확인을 해야한다.

정리

박싱에는 값을 단순히 참조에 할당하는것보다 최대 20배의 시간이, 언박싱은 할당의 4배의 시간이 소모된다고 한다.
되도록 제네릭을 사용해서 박싱,언박싱을 피해야한다.

참조 https://hongjinhyeon.tistory.com/90

 

[C#] 박싱 과 언박싱 (Boxing & UnBoxing)

일반적인 프로그램을 만들면 이 개념에 대해서 몰라도 개발은 가능합니다.그러나 사용되는 메모리가 많거나 관리가 필요하다면 필수적으로 알아야할 내용입니다. 1.박싱(Boxing) 값타입을 Object

hongjinhyeon.tistory.com

 


작성일: 2022년 12월 9일

'아카이브 > 개발,공부' 카테고리의 다른 글

유니티,깃 협업 환경 세팅 (팀원 공유용)  (0) 2026.05.12
객체지향 프로그래밍  (0) 2026.05.12
Generic  (0) 2026.05.12
상속, Virtual , Abstract, Interface  (0) 2026.05.12
UnityWebRequest 정리  (0) 2026.05.12

클래스의 상속

클래스는 상속을 할 수 있다.
상위 클래스는 부모, 하위 클래스는 자식(child)클래스 라고 부른다.

클래스의 상속은 병렬로는 여러개가 이뤄질 수 없고, 직렬로는 차곡차곡 상속이 가능하다.
자식클래스는 부모클래스의 기능을 모두 사용한다.

//이 클래스는 씬에 놓여있지 않음.
public class ParentTest : MonoBehaviour
{

    private void Awake()
    {
        Debug.Log("부모");
    }
}
//이 클래스는 씬에 놓여짐.
public class playerTest : ParentTest
{
    //아무것도 구현하지않음.
}

Log:
부모

Virtual (가상 키워드)

가상 메소드는 한마디로 자식에게 물려줄 수 있는 메소드다.

위의 상속 부분에 적혀있듯 자식은 부모의 메소드를 자동으로 사용하게 되지만,
때에따라 부모의 메소드를 변형해서 사용하거나, 추가해서 사용하고 싶을 수 있다.

이때 해당 부모 메소드에 Virtual키워드를 적어준다.
그리고 자식에 는 override키워드 같은이름의 메소드를 구현해주면 새롭게 덮어쓰기 해서 구현할 수 있다.

말 그대로 덮어쓰기 이므로, 부모에게 구현되어있던 기능들은 사용할 수 없는데,
base.메소드(); 를 사용하면 부모에 구현되어있던 기능들도 사용할 수 있다.

Virtual 메소드를 덮어쓰기 할지말지는 자식 클래스의 마음이다.
강제성이 없다.

//이 클래스는 씬에 놓여있지 않음.
public class ParentTest : MonoBehaviour
{

    protected virtual void Awake()
    {
        Debug.Log("부모");
    }
}
//이 클래스는 씬에 놓여짐.
public class playerTest : ParentTest
{
    protected override void Awake()
    {
        base.Awake();
        Debug.Log("자식");
    }
}

Log:
부모
자식

Abstract(추상 키워드)

추상은 가상 메소드와 비슷하다.
부모의 Abstract 메소드에는 구현부가 없다. 말그대로 추상적으로 존재만 한다.

대신 자식이 override 해서 구현을 해줘야한다.
부모에게 추상 메서드가 있다면 자식은 강제로 구현해야한다.

활용
아래처럼 자식 클래스들에게 공통적인 정의를 내려주고, 자식들은 각각 다르게 부모가 내려준 정의를 다르게 구현한다.

//이 클래스는 씬에 놓여있지 않음.
public abstract class ParentTest : MonoBehaviour
{

    protected virtual void Awake()
    {
        Debug.Log("부모");
        Habit();
    }

    protected abstract void Habit();
}
//이 클래스는 씬에 놓여짐.
public class playerTest : ParentTest
{
    protected override void Awake()
    {
        base.Awake();
        Debug.Log("자식");
    }

    protected override void Habit()
    {
        Debug.Log("다리떨기");
    }
}

Log:
부모
다리떨기
자식

Interface

언뜻보면 상속과 비슷하다. 변수를 사용할 수 없고, 메서드에대한 정의나 프로퍼티만 가질 수 있다.
클래스상속과 다르게 인터페이스는 병렬로 여러개 상속받을 수 있다.

abstract와 마찬가지로 인터페이스에 정의된 메소드는 무조건 상속받은 클래스에서 구현해줘야한다.

//인터페이스는 파일이름 맨 앞에 I 붙임
public interface ITest
{    
    public void SaChoonGi();
}
//이 클래스는 씬에 놓여짐.
public class playerTest : ParentTest , ITest
{   
    protected override void Awake()
    {
        base.Awake();
        Debug.Log("자식");
        SaChoonGi();
    }

    protected override void Habit()
    {
        Debug.Log("다리떨기");
    }

    public void SaChoonGi()
    {
        Debug.Log("반항");
    }


}

Log:
부모
다리떨기
자식
반항

정리

-Vritual은 하나의 기능을 하는 완전한 클래스이며, 자식클래스에서 상속해서 추가적인 기능추가 및 virtual 한정자가 달린 것을 재정의해서 사용가능하다.

-Abstract는 여러개의 자식 클래스에서 공유할 기본 클래스의 공통적인 정의만 하고 ,자식클래스에서 abstract 한정자가 달린 것을 모두 재정의(필수)해야 한다.

-Interface에서도 abstract와 비슷하지만 멤버변수를 사용할 수 없다.

  • 보통 abstract는 개념적으로 계층적인 구조에서 사용이 된다.
    ex)동물(움직이기)/포유류(새끼 낳기)/강아지
  • Interface는 서로다른 계층이나 타입이라도 같은기능을 추가하고 싶을때 사용합니다.
    로봇(말하기) , 사람(말하기) , 지나가는 비둘기(말하기)

참조 https://hongjinhyeon.tistory.com/93

 

[C#] Virtual(가상) vs Abstract(추상) vs Interface(인터페이스)

OOP개념에서 상속을 이야기할 때 Virtual이나 Abstract 한정자가 사용이됩니다.두개를 사용하면서 헷갈리는 점을 정리했습니다. 또한 Interface와 비슷한 기능을 제공하는데같이 비교해보겠습니다. 1.Vi

hongjinhyeon.tistory.com

 


작성일 2022년 12월 5일

 

'아카이브 > 개발,공부' 카테고리의 다른 글

유니티,깃 협업 환경 세팅 (팀원 공유용)  (0) 2026.05.12
객체지향 프로그래밍  (0) 2026.05.12
Generic  (0) 2026.05.12
값 타입, 참조 타입 / Boxing, UnBoxing  (0) 2026.05.12
UnityWebRequest 정리  (0) 2026.05.12

+ Recent posts