[유튜브 강의] (5) JAVA 초급 강좌 - 형 변환 : 2. 클래스끼리의 형변환

2017. 3. 1. 20:50[유튜브 강의]- 센치한 개발자/[JAVA] 자바 기초 강의 - 완료

728x90

[센치한 개발자-유튜브 강의] (5) JAVA 초급 - 형 변환 : 2. 클래스끼리의 형변환 :: 기초 강의












[자료 목차]

1> 형 변환

  (1) 기본 타입끼리의 형 변환

    1. 자동 변환 (묵시적 ) - promotion

    2.강제 변환 (명시적) - casting


  (2) 클래스끼리의 형 변환

    1. 업 캐스팅 & 다운 캐스팅 - up & down casting


[ 미리 생각해볼 문제 ]


*. 클래스Class를 왜 만드나요?

 클래스Class는 우리 일상생활속의 모든 것(사물, 현상, 성질 등)중에서 하나를 정해서 그것을 컴퓨터의 코드로 정의해 놓은 "틀"입니다.

 틀만 만들어 놓으면 어디서든지 자동차를 생산할 수 있는 것이지요.


 그 생산을 자바에서는 "객체를 생성한다"고 표현하며, "new 클래스이름()" 과 같은 방법으로 생산합니다.

 

 예를 들어 자동차를 프로그래밍 코드로 만들어 놓고 수십, 수백대의 차를 생산하고 싶으면 "자동차"라는 클래스 틀을 만들고 그 안에 기름넣기, 브레이크, 바퀴, 유리창 내리기 올리기 등의 각 기능들을 정의해 놓습니다. ( 이러한 기능들을 함수 또는 메소드)라고 합니다~


그러고나서 new 자동차(); 라고 객체를 생산해내서 클래스라는 틀을 갖다 쓰면 되죠~

 

물론 브레이크나 바퀴라는 기능들에 대해서 좀 더 다양하게 만들고 싶으면, 브레이크나 바퀴도 클래스 틀로 만들고 세부적인 기능들을 다시 만들 수도 있습니다~


*. 그럼 클래스를 왜 바꿔가며 쓰나요? (형변환을 왜하는가요?) 

- 우리 일상에서 가장 밀접한 "김치"를 생각해볼까요. 김치라는 녀석을 클래스라고 생각해봅시다. 어우, 조리법에 따라 나오는 김치가 들어가는 음식의 종류가 다양합니다. 

김치라는 클래스를 만들어 놓으면 김치전, 김치찌개, 참치김치찌개, 물김치, 백김치.. 아 배고파.


이렇게 프로그래머가 클래스를 하나 만들어 놓으면 다음 프로그래머가 김치를 건네 받아서(상속) 뭘 만들지 고민하다가 

마음껏 지지고 볶습니다.


이렇게 지지고 볶다보니 앞사람이 만들어 놓은 클래스 틀에서 함수(메소드)를 그대로 사용하기도 하고 


다시 본인의 입맞에 맞게 재정의해서 무를 쎃어 넣거나 파를 넣거나 합니다. 아, 더 배고파.


결국 이 모든 과정들을 하다보면 여러 클래스들을 이리저리 형변화하며(바꿔가며) 만들어가는 것이지요~


빨간 김치를 물에 씻어서 백김치로 만들었다가 다시 고춧가루에 버무려서 다시 빨간 김치로 만들어도 된다는 겁니다.


물론 자바에서 클래스끼리 형변환을 하다보면 맘대로 안되는 경우도 있지요..


그건 저 밑에서~~

 


*. 아니 근데, 클래스끼리 바꾸는 건데 왜 "클래스 변환"이라고 안하고 "형변환"이라고 표현 하나요??

클래스를 객채라고 했던 것 기억나시나요~?


엄밀한 의미에서 클래스 자체를 객체라고도 하고 클래스를 갖다 쓸때 객체를 생성한다고도 하지만, 


이보다 중요한건, 객체는 하나의 "형태"입니다. 


특정한 클래스를 쓰겠다고 해놓고 다른 클래스로 바꾸게 되는 것은 객체에서 다른 객체로 바꾸는 것이고


같은 객체라는 이름을 가졌어도, 그 객체안의 클래스 내용, 즉 그 틀, 형태가 바뀌는 거니까, "형"변환이라고 할 수 있습니다~



[ 본격적으로 클래스 형 변환을 위해 클래스 좀 만들고 변환을 해봅시다 ]



클래스의 예를 자동차로 드는 것이 거의 불문율(?)이다보니 우리도 자동차로 만들어 볼게요~


자동차는 동력을 기준으로 크게 다음과 같이 종류를 나눌 수 있겠죠?  

휘발유 / 경유 / 가스 / 전기 (기타..뭐 수소차 ~ )


용도로 나누면,

자가용(영업용), 쓰레기수거차, 경찰차, 소방차 등~


배기량이나 용도로 나눈다고 하면 또 다양한 분류가 생길 수 있겠네요~

 


클래스를 형변환 하려면 Object 클래스와 이를 상속받은 String 클래스를 예로 드는 것이 실무에서는 가장 흔한 예일겁니다~만~


그건 동영상 강의에서 맛보기로 보여드릴게요~ 왜 그게 가장 흔한지도..



일단 지면에서는 이론을 익히는 것이니 아래처럼 클래스를 한 번 만들어 보죠~



1. 자동차 클래스 만들어보기위해 정의를 먼저해보자~


자동차 - 휘발유, 경유, 가스, 전기 등을 채워서 4개의 바퀴로 빠르게 달리는 사물 - 핵심기능은 "drive" 


휘발유차 - 휘발유를 채워서 이를 동력으로 달리는 자동차 - 핵심 기능 가솔린을 넣어야 한다. fillGasolin

경유차 - 경유를 채워서 달리는 자동차 -  경유를 넣는다. fillDiesel

가스차 - 가스를 채워서 달리는 자동차 - 가스를 채운다. fillGas

전기차 - 전기를 충전해서 달리는 자동차 - 전기를 충전한다. chargeElec


2. 이를 말로 정의해보면 아래와 같아요.


휘발유차는 자동차이다. (자동차의 하위개념, 종류이다),  > 즉, 휘발유차(class)는 자동차(class)를 상속(extends)받은 자동차의 한 종류이다.

경유차는 자동차이다. (자동차의 하위개념, 종류이다), > 즉, 경유차(class)는 자동차(class)를 상속(extends)받은 자동차의 한 종류이다. 

가스차는 자동차이다. (자동차의 하위개념, 종류이다), > 즉, 가스차(class)는 자동차(class)를 상속(extends)받은 자동차의 한 종류이다.

전기차는 자동차이다. (자동차의 하위개념, 종류이다), > 즉, 전기차(class)는 자동차(class)를 상속(extends)받은 자동차의 한 종류이다.


3. 그리고 클래스로 직접 코딩해보면 아래와 같아요.


public class Car {
    public void drive();
}

class 휘발유차 extends Car {
    public void fillGasolin();
}

class 경유차 extends Car {
    public void fillDiesel();
}

class 가스차 extends Car {
    public void fillGas();
}

class 전기차 extends Car {
    public void chargeElec();
}



여기서처럼 상속받은 녀석이 존재하게 되면, Car는 "부모" 클래스 - 그 외 휘발유~전기차 클래스들은 "자식" 클래스라고 합니다~


또는 부모는 상위, 자식은 하위 클래스라고도 합니다.




4. 그럼 아까 2번처럼 했던 내용을 어순을 바꿔서 반대로 말을 해보면 어떨까요?


"자동차는 휘발유차이다" 


읭? 뭔가 어색하죠?


(어색하지 않다면 당신은 천재....)




상속이 발생하고 말을 만들어 놓으면 그 문장의 주체와 객체를 바꾼 어순의 말은 어색해집니다.


즉 자식 클래스는 부모 클래스이다. 는 성립하지만,


부모 클래스는 자식 클래스이다. 는 성립하지 않게 됩니다~


이를 잘 기억해 두시고요~




5. 그럼 본격적으로 클래스를 선언해보고 형변환 해볼게요~


*. 클래스의 기본 선언과 생성법

휘발유차 휘발 = new 휘발유차();

경유차 경유 = new 경유차();

가스차 개스 = new 가스차();

전기차 전기 = new 전기차();


이건 아주 기본적인 클래스 생성방법입니다. 아까 위에서 new 클래스이름(); 과 같은 방법으로 사용하고, 이를 객체를 생성한다고 말씀드렸죠~


그럼 이번에는 특이하게 좀 꼬아볼까요~



[ 결론부터 말하면 업캐스팅 ]

자동차 차 = new 휘발유차();

자동차 차 = new 경유차();

자동차 차 = new 가스차();

자동차 차 = new 전기차();


왼쪽은 부모 오른쪽은 자식의 형태로 되어 있습니다.


자바의 기본 값 대입 ( 벌써 까먹으신건 아니겠지요.. ) 은 오른쪽의 녀석을 왼쪽으로 넣는다는 뜻이므로,


자식을 생성해서 자동차(부모) "차"에 넣었습니다.


자식에서 부모로 간 이러한 생성동작을 "업 캐스팅" 이라고 하는데, 


자식들 입장에서 아버지는 1명이니까 그냥 올라가는 형변환은 가능합니다.



그럼 반대로 다시 자식으로 내려가 볼까요.


[ 결론부터 말하면 다운 캐스팅

휘발유차 휘발 = (휘발유) ;

경유차 경유 = (경유차;

가스차 개스 = (가스차;

전기차 전기 = (전기차;


왼쪽은 자식 클래스이고 오른쪽은 아까 부모클래스의 변수 이름이었던 "차"가 있는데,


그 앞에 괄호() 표시가 있죠. 이걸 왜쓰는 걸까요.


부모 입장에서는 자식이 여려명일 수 있기 때문에, 어떤 자식을 이야기하는 것이냐고


"명시적"으로 선언해줘야 합니다.


기본 타입을 형변환 하던 기억이 급 떠오릅니다. ( 지난시간 강의에서 분명히.....말했... )



그런데!!!!


왜 아래와 같은 다운 캐스팅은 불가능한가요!!!!!


경우 1. [ 결론부터 말하면 런타임 에러(자바가 원하는 문법-컴파일-은 통과했지만 실행해보니 안되네~하는 상태)가 나는데,  new로 생성하자마자 갑자기 자식으로 내려가는 것은 불가능! ]


휘발유차 이런휘발 = (휘발유) new 자동차(); 

경유차 경유 = (경유차) new 자동차();

가스차 깨스깨스 = (가스차) new 자동차();

전기차 전기 = (전기차) new 자동차();


경우 2. [ 이건 결론부터 말하면 컴파일 에러가 나는데 new로 생성해놓고 무턱대고 자식을 낳는 건 불가능 ]

휘발유차 이런휘발 = new 자동차(); 

경유차 경유 = new 자동차();

가스차 깨스깨스 =  new 자동차();

전기차 전기 = new 자동차();



경우1번, 2번 모두 공통점은 왼쪽이 자식, 오른쪽이 부모인데 부모를 new 클래스 이름(); 으로 만들고 있습니다.


new 클래스이름(); 이라고 하는 동작은 "객체를 생성"하는 것이라고 말씀드렸습니다.


그런데 객체를 만들자마자 어디로 들어가야할지도 모르는 상태(new 클래스이름()상태에서는 아직 아무런 정보가 없음) 에서 


갑자기 (휘발유)라는 자식클래스로 바꿔버리거나 그냥 쌩자로 =으로 대입을 하게 되면


부모클래스 입장에서는 생성은 했지만 (new~~)  나는 나를 모르는데 남들너를 알겠느냐며, 내 자식을 찾아가라는 것이냐며 에러를 뿜게 되는 것이지요.



자.. 슬슬 복잡해지죠.


그럼 다시 봅시다.


new 를 해서 만들고 부모로 대입한 


자동차 차 = new 휘발유차(); 


이 내용은 업 캐스팅이었죠.  


아놔~!!!


new 휘발유를 했을때 휘발유는 아무런 정보가 없는데 그럼 어떻게 그냥 자동차라는 부모클래스에 넣을 수 있나요?? 정보가 있어야 한다면서요!!!!


끙.. 그게 바로 자바가 자동으로 클래스를 형변환하는 "업 캐스팅"의 특징입니다. 자식을 생성해서 부모로 바로 넣는 것은 가능합니다.


왜일까요!!!!


휘발유차()라는 클래스는 extends라고 나의 부모는 "자동차" 클래스요 라고 미리 만들어놨기때문이죠...


( 그런데 부모에는 자식이 누구입니다 라고 써놓은 적이 없죠... )



new로 부모를 만들고 바로 자식에게 대입하는 "다운 캐스팅" 방식은 불가능하다는 겁니다.


그래서 다운캐스팅을 해야한다면 


자동차 차 = new 휘발유차();  //내 부모는 자동차라는 것을 나는 미리 적어놨으니 부모를 찾아 떠날래


이렇게 업캐스팅으로 만든 녀석처럼 "휘발유"라는 자식의 정보를 담고 생성한 상태에서


휘발유차 휘발 = (휘발유) ; //그래, 나는 원래 휘발유였어... 자식으로 돌아갈래


라고 다시 다운 캐스팅해야만 아무 에러가 없다는 겁니다.


최소한의 정보를 담고 있는 상태에서 다운 캐스팅을 해야 한다는 것으로 이해할 수 있겠네요~~



한 줄로 요약하면, 


부모 클래스는 자식클래스에 extends라고 적힌 "내 부모는 당신이요" 라는 정보를 일단 알아야 자바가 자동으로 형변환(업캐스팅)을 시켜주면서 정보를 들고 다녀야만, 다시 자식으로 돌아가는 형변환(다운 캐스팅)을 할때 "아 네가 내 자식이구나." 라고 에러 없이 돌아갈 수 있는 것이죠.



어우, 나와토네요.


클래스 공부할때 다시 설명할게요~~


고생하셨어요~~


+초급이 싫어







728x90