ecsimsw

OOP / Up Casting / Down Casting 본문

OOP / Up Casting / Down Casting

JinHwan Kim 2019. 1. 18. 08:12

Casting

  • Introduction
    - Dev korea에 c# 상속/ casting에 대한 질문을 보게 되었고, 사용법 자체를 중요시 했던 처음 c# 공부와 다르게 이번에는 그게 객체지향 측면에서 왜 중요한지, 실제 어떤 개념을 구현할 때 필요할 지를 고민하면서 Casting과 상속에 대해서 공부하였다.
    - 이번 캐스팅 관련 공부 목표는 다음 두가지이다.
    1. 'Up casting / Down casting' 을 왜 사용하는가
    2. 'Parent objectName = new Child()' 가 의미하는 바가 정확히 무엇인가.
  • Up casting / Down casting
    Example _ up casting
    - 다음의 예시를 생각해보자. 3가지 경주용 자동차가 있고, 자동차의 시동을 거는 방법은 차종에 따라, '열쇠를 넣어 돌리기, 버튼 누르기, 지문 인식'으로 모두 다르다.
    경주를 위해 세 자동차가 출발하도록 레이서에게 지시하려면 어떻게 해야할까
      가장 빨리 떠오르는 생각은 각 차종별로 레이서에게 차종에 맞는 시동 방법을 지시하는 것이다. 그것으로 조금은 비효율적이지만 모든 자동차가 출발하도록 지시 할 수 있을 것이다.
      하지만 만약 이런 차의 종류가 3가지가 아니라 훨씬 큰 숫자면 어떻게 할까. 아마 레이서에게 각각의 시동방법을 알려주다가 경기 시간이 다 사용될 것이다. 시동을 거는 시간이 너무 차이가 커 공정한 레이싱을 기대하긴 힘들 것이다.
    - 만약 이런 상황에서 좀 더 능숙한 사람이라면 사전에 레이서들에게 시동거는 다양한 방법들을 교육시키고 한번에 '시동을 켜'로 지시할 것이다. 그럼 훨씬 효율적이고 공정한 레이싱이 가능할 것이다.
      이 방법을 코드로 구현한 것이 상속과 캐스팅이다.
    "Up casting" class Program { static void Main(string[] args) { Car[] Racers = { new CarA(), new CarB(), new CarC()}; foreach (Car racer in Racers) { racer.Start(); } } } class Car { public virtual void Start() { Console.WriteLine("Start!!"); } } class CarA : Car { public override void Start() { Console.WriteLine("키를 넣고 돌려 시동 걸기"); } } class CarB : Car { public override void Start() { Console.WriteLine("버튼을 눌러 시동 걸기"); } } class CarC : Car { public override void Start() { Console.WriteLine("지문을 인식시켜 시동 걸기"); } }
      위 설명처럼 우선 "Car[] Racers = { new CarA(), new CarB(), new CarC()}" 을 통해 현재 생성된 CarA, CarB, CarC를 각각 따로 명명하는 것이 아니라, Car 배열에 업캐스팅하여 "자동차들"으로 지칭하고,
      오버라이딩으로 시동거는 방법에 다형성을 주어 "자동차.시동걸다" 한번의 명령으로 모두 다른 자동차의 신호걸기를 수행할 수 있는 것이다.

    Example _ down casting
    - 이번에는 유사하지만 좀 다른 상황을 생각해보자. 개별적인 것을 집합화하고 그것을 한번에 관리하는 것에 목표를 두는 것이 아니라, 집합화된 것 안의 개별적인 객체의 기능에 집중하는 것이다.
      예를 들어 레이싱 상황이라면 "여러 종류의 자동차를 한 집합에 묶어 한번에 관리하였다."에 집중하는 것이 아니라 "집합화된 자동차들 중에 독특한 기능을 갖은 자동차" 처럼 개별적인 기능에 집중하는 것이다.
      이럴 때는 "Parent object = new Child" 에서 object의 참고 범위가 Parent에 한정되기 때문에 object를 Child로 다운 캐스팅하여 그 레퍼런스 범위를 확장 시켜야한다. 즉 기존의 "자동차"가 아니라 이번에는 "드리프트가 가능한 자동차" 처럼 자식 클래스로 명명해야 하는 것이다.
    "Down casting" class Program { static void Main(string[] args) { Car[] Racers = { new CarA(), new CarB(), new CarC(), new CarA()}; CarA driftCar; foreach (Car racer in Racers) { racer.Start(); if(racer is CarA) { driftCar = (CarA)racer; driftCar.Drift(); } } } } class Car { public virtual void Start(){} } class CarA : Car { public override void Start(){ Console.WriteLine("A"); } public void Drift() { Console.WriteLine("Drift"); } } class CarB : Car { public override void Start(){ Console.WriteLine("B"); } } class CarC : Car { public override void Start(){ Console.WriteLine("C"); } }
  • Parent object = new Child()
    - 개념을 찾아보고, 다른 사람이 고민한 부분을 해결해보고, 스스로 예시를 만들어가면서 그래서 "Parent object = new Child()" 가 의미하는 바가 무엇인가에 대해서 생각해본 결과이다.
    집합화 측면
      사용 측면에서, oop 효용 측면에서 Parent object = new Child()은 집합화라고 생각한다. 같은 기능을 하거나, 같은 부류의 객체들을 부모라는 집합으로 묶어 명명하는 것이다.
      길에서 보이는 수많은 자동차들을 보고 오토바이, 트럭, 승용차라고 부르는게 아니라 "차"라고 한번에 묶어 부르기위한 도구라고 생각한다.
    참조 측면
      Parent object = new Child()에서 object는 Parent형이다. 이는 다른 말로 parent 객체를 참조하는 변수이고 new child가 하는 역할은 참조할 수 있는 메모리 범위를 더 큰 child로 일단 잡아둔다는 것이다. 우선은 부모 클래스를 참조하되, 힙에는 자식 클래스의 메모리를 할당하여 원할 때 자유롭게 변경 가능한 것이다.
  공부전에는 그저 캐스팅의 개념만 알고 사용할 줄만 알고, 이것이 뭐를 가리키며 어떤 것을 참조하고 왜 이런식의 제한이 생기는지 몰랐다. casting을 왜 사용하는지 조사하는 것을 통해 oop 개념을 조금이나마 더 이해할 수 있었고, 다른 사람들의 질문을 보고, 왜 이런 제한이 생기고, 어떻게 구현되는지를 이해하면서 메모리의 측면도 공부할 수 있었던 계기가 되었다.

'Language > C++, C#' 카테고리의 다른 글

C# / Iterators/ IEnumerator, IEnumerable / yield  (0) 2019.03.01
C# / Is와 As  (0) 2019.01.18
OOP / Class vs Struct / Memory aspects  (0) 2019.01.16
OOP / Encapsulation  (0) 2019.01.15
Reference type / Value type  (0) 2019.01.14
Comments