2011년 5월 5일 목요일

자바의 상속에서 상위 클래스를 지칭하는 명령어(super)

자바의 상속을 배우면서 꼭 알아야할 키워드가 바로 super 이다. 자식 클래스에서 객체 생성을 하면 자동으로 super( )를 이용해 자식 생성자를 실행하기전에 먼저 부모 생성자를 호출하고 실행한다. 따라서 super를 모르고서는 자바의 상속에 대해서 안다고 말하는 것이 어불성설인 것이다.


상위 즉 부모 클래스의 멤버들을 사용하기 원할때 super 라는 명령어를 쓰는데 쓰는 방법은 아래와 같다.

super.변수;                       //부모 클래스의 변수를 호출한다.
super( );                            //부모 클래스의 생성자를 호출한다.
super(매개변수);              //부모 클래스의 생성자(입력값)를 호출한다.
super.메소드( );                //부모 클래스의 메소드를 호출한다.
super.메소드(매개변수);  //부모 클래스의 메소드(입력값)를 호출한다.

보면 알겠지만 예전에 배운 this 대신에 super를 쓴것과 같다. 생성자안에서 다른 생성자를 호출할 경우 this( )나 super( )나 해당구문 맨첫줄에 써야하며 this가 자기자신을 말하는거였다면 super는 자기자신을 있게해준 부모를 말하는 것이라 하겠다. 더 자세하게 설명하자면 super는 바로 한단계 위로 올라간다고 생각하면 된다. 자바에서 부모는 위대하다. 왜? super니까 말이다.ㅎㅎ

super라는 키워드를 공부할때는 다 알것 같은데 막상 쓰다보면 굉장한 혼동이 올것이다. 그 이유중의 하나가 this처럼 단순히 super라는 키워드만 공부하면 되는게 아니라 상속관계에서 오는 파장(?)까지 고려해야하기 때문에 대부분이 안다고는 하나 딱히 자신있게 super에 대해서 논할수 있는 이가 그리 많지 않다. 오늘 이 강좌를 아니 필자가 보여주는 예제 하나만 확실하게 이해한다면 super라는 키워드에 대해서 앞으로 고민하지 않아도 될것이라 확신한다.^^

예제에 들어가기에 앞서 오늘 강좌 제일 첫부분에 언급한 super( )에 대해서 여러분의 이해를 돕기위해 한번더 짚고 넘어가도록 하겠다.^^ 객체생성 강의에서 아직 super에 대해서 설명하지않은 상태라 혼란을 피하기위해 잠시 뛰어넘었지만 여러분이 기본적으로 알아야할 용법이 있다. super( )는 부모클래스의 기본생성자를 호출하는 명령인데 이게 여러분이 new를 이용한 클래스의 객체생성시 해당클래스내의 기본생성자에 super( )라는 구문이 없을 경우에도 자동으로 항상 작동된다는 점이다. 다시 설명하자면 여러분이 객체생성을 할 경우 해당클래스내에 다른 생성자가 없을경우 자동으로 빈껍데기만이라도 있는 기본생성자를 만드는데 이안에 super( )도 자동으로 만들어지고 또한 다른 생성자가 있을 경우에는 기본생성자가 만들어지진 않겠지만 이 경우에도 해당 생성자안에 따로 super구문을 만들지 않았다면 객체생성시 해당 생성자안에서 역시 super( )가 여러분이 실행하는 해당클래스의 객체생성시 처음에 자동으로 작동된다는 점을 기억해야 한다.

그럼 이런 의문이 들것이다. 생성자는 모든 클래스안에 빈껍데기라도 있다고 하였는데 부모클래스가 없는 즉 상속받지 않은 클래스에서도 super( )가 자동으로 작동된다고 보아야할텐데 이건 어떻게 생각해야 되는건지 의문이 들것이다. 자바는 모든 클래스들의 단군 할아버지격(?)인 Object 클래스를 암묵적으로 계승하고 있다. Object가 모든 클래스들의 최상위 클래스라고 부를수 있는 것이 이에 기인한다. 즉 직접적인 상속관계가 없다면 기본적으로 모든 클래스들의 부모클래스인 Object 클래스의 기본생성자를 호출한다고 생각하면 된다. 여기서 또 질문하는 이들이 있을 것이다.ㅎㅎ 그럼 Object 클래스가 최상위 클래스인데 거기서는 누구를 호출한단 말인가? 아주 날카로운 질문이다.ㅎㅎ 그래서 Object 클래스의 기본생성자에는 super( )가 자동으로 호출되지 않는다. 따라서 여러분이 생각하는 부모클래스에서 super 구문이 없을경우 super( )를 자동으로 호출해서 상속관계 여부에 따라 계속적으로 위로 거슬러 올라갈수 있겠지만 결국 최종 종착지는 기본생성자안에 super( )가 없는 Object 클래스가 될것이다. 이 정도면 여러분의 궁금증이 해소되었으리라 생각되니 하던 강의를 계속 진행하겠다.^^

방금 말한 것처럼 예제 딱 하나 더도말고 딱 하나만 준비했다. 상속에서 super와 객체생성에 얽힌 모든 핵심을 이 예제에 담았다. 본 예제는 조금 긴 관계로 여기를 누르고 다운하기 바란다. 예제에 주석을 아주 풍부(?)하게 담았으나 이해를 돕기 위해 한줄 한줄 장인정신(!)으로 똘똘 무장해서 자세한 설명을 곁들이겠으니 잠시나마 집중해서 본 내용을 자기 것으로 만들기 바란다.*

1000
===인자 a가 있는 Parent 생성자===
부모는 자동차를 소유
이제는 자식도 자동차를 소유
자식만 배를 소유
100이 super.money값이다.
300이 this.money값이다.
===나는 Child 기본 생성자===
300
이제는 자식도 자동차를 소유
부모는 기차를 소유
200
자식만 배를 소유
300
===나는 Parent 기본 생성자===
===인자 b가 있는 Child 생성자===
555
==============================
1000
===인자 a가 있는 Parent 생성자===
부모는 자동차를 소유
이제는 자식도 자동차를 소유
자식만 배를 소유
100이 super.money값이다.
300이 this.money값이다.
===나는 Child 기본 생성자===
이제는 자식도 자동차를 소유
부모는 기차를 소유
==============================
===나는 Parent 기본 생성자===
부모는 자동차를 소유
부모는 기차를 소유

예제의 출력 결과가 좀 길지만 긴만큼 여러분이 그동안 아리까리했던 많은 부분들을 좀 더 명확하게 알수있는 계기가 될것이다. 예제의 전체적인 개요를 듣고 코드를 보면 어려울건 없다. 본 예제는 이러하다. 총 3개의 클래스, 부모 클래스(Parent), 자식 클래스(Child), 그리고 메인메소드만 있는 Test41 클래스가 있다. 부모 클래스와 자식 클래스에는 각각 두개의 생성자와 두개의 메소드가 있다.  부모는 차(car)와 기차(train)가 자식은 차(car)와 배(ship)를 메소드 형태로 소유하고 있다. 당연하지만 클래스 이름에서 보듯이 자식은 부모 클래스를 상속받고(extends) 있다.

이제 메인 메소드에서 실행하는 명령들을 살펴보자. 각기 다른 객체 생성을 통해 변수와 생성자 그리고 메소드의 상호관계를 총 3가지 파트로 나누어 살펴보기 위한 예제이다. 보기 좋으라고 "==========" 분리선을 이용해 출력결과를 파트별로 분류하였다.

그럼 이제 예제 프로그램 속으로 들어가보자. 첫번째 파트는 Child t=new Child();이다. 자식 객체 생성이다. 자식(Child)에 인자가 없으니 기본 생성자가 있는 곳으로 간다. 가서 보니 맨 첫줄에 super(1000);을 만난다. super는 부모클래스를 말하고 형태가 1000을 입력값으로 가질수 있는 생성자를 찾아보면 Parent(int a)로 가야됨을 알수 있다.(여기서 super(1000);이라는 부모 생성자 호출기능이 없었다면 기본값인 super( ); 즉 부모 기본 생성자를 자동으로 호출했을 것이다. 자식의 어떤 생성자든지 부모 기본 생성자 호출기능이 눈에 보이지는 않지만 자동으로 삽입된다.)

인자 a를 가진 부모 생성자로 가면 돈을(money 변수)에 1000(원) 받고 그걸 출력하라고 하니 결과에서 첫줄에 1000이 찍히고 다음줄에 "===인자 a가 있는 Parent 생성자==="라는 글이 출력된다. 끝나면 아까 실행하던 자식 생성자로 다시 돌아와서 다음줄을 실행한다. super.car( ); 주석에서 보듯이 부모의 차 메소드로 간다. 돈 100원 받고 "부모는 자동차를 소유"라고 알려주란다.ㅎㅎ

자식생성자의 다음줄을 또 보면 car( ); 차 메소드를 가란다. 그런데 여기서 조금 헤깔릴수가 있다. 리턴값(결과값)과 인자(입력값)가 완전히 똑같은 car 메소드가 부모한테도 있고 자식한테도 있기 때문이다. 이렇게 겉껍데기가 완전히 동일한데 상속받아서 다시 구현한 형태를 우리는 오버라이딩(Overriding)이라고 말한다. 저번에 필자가 상속부분에서 잠깐 이야기했을 것이다.(잠시 이해를 돕기 위해 얘기하자면, 자바의 다형성(polymorphism)에는 크게 오버라이딩과 오버로딩이 있다. 오버라이딩은 방금처럼 매개변수, 리턴값, 메소드 이름까지 전부 동일한 형태를 말하고 오버로딩(Overloading)은 인자 즉 매개변수나 리턴값은 다르지만 메소드 이름이 같은 형태를 말한다. 이렇게 동일한 형태로 다른 형태의 멤버들을 제어할수 있을때 이것을 자바의 다형성이라고 하는 것이다. 따로 단원을 만들어 강좌를 진행하려고 했는데 이미 오버로딩도 전부터 예제에서 계속 써먹고 있으니 모르는 이는 없을 것인즉 그냥 이걸로 퉁치려고 하니 양해바란다.ㅎㅎ )

갈길이 먼데 자꾸 삼천포로 빠지고 있구나. 이제 예제로 다시 돌아가보자. 어디 할 차례더라?? 올커니 car 메소드 때문에 이런 얘기가 나왔구나. 그런데 같던지 다르던지 상관없다. 상속을 받았으니(자식 클래스안에 부모의 car( ) 메소드가 있다고 생각) 자식 클래스가 가지고 있는게 더 확장 발전시킨걸로 간주하고 같을 경우 자식이 소유한 것을 쓴다고 이미 말했었다. 따라서 자식의 car( )를 실행한다. 그래서 돈(money) 200원 받고 "이제는 자식도 자동차를 소유"라인을 출력한다. 다음줄에 ship( )은 자식만 가지고 있으니 가차없이 이걸 실행하면 돈 300원을 받고 "자식만 배를 소유"라인을 출력한다.

이제 super.money와 this.money를 찍을 차례이다. 오늘의 하이라이트라고 해도 괜찮을 것이다. super에는 100원이 this에는 300원이라는 돈이 출력되었다. 왜 그럴까? money 변수는 부모에게도 있고 자식에게도 있다. 이럴 경우 제각기 돌아간다. 부모 클래스에 money에 관련된 명령은 super.car( )에서 즉 돈 100원을 받았을때까지이고 자식 클래스에서 money에 관련된 명령은 ship( )에서 즉 돈 300원을 받았을때까지가 돈의 흐름(?)이다. 헤깔리면 다시 차근차근 보면 이해가 될 것이다. 필자가 예제를 풀이하면서 설명하니 별 어렵지 않다고 느낄지 모르지만 상속 관계에서 super로 인한 혼선이 이런 식으로 가중되고 증폭되는 것이다. 간단한 예지만 느끼는 바가 크길 바란다.^^

이제 "===나는 Child 기본 생성자==="라인을 출력하고 다 했으니 메인메소드로 돌아온다. 보면 알겠지만 이제까지 고작 Child t=new Child( ); 이거 한줄 실행한 것이다.--; 그렇다고 슬퍼말자. 이거 한줄 이해하면 그 다음부터는 일사천리(?)일 것이다. 쩡말? ㅎㅎ 다음줄은 자식 돈이니까 똑같이 300원을 출력한다.

t.car( ); 자식이 우선이니 자식의 car( ) 메소드 실행해서 출력하고 t.train( ); 메소드는 자식 클래스에는 없지만 부모한테서 물려받았으니 기차 메소드 또한 출력할수 있다. 상속받은게 뭔지(?) 모두 알고 있기를 바란다. 그리고 t.money 즉 자식이 돈 지금 얼마 가지고 있냐를 물었더니 200원이란다. 이해되는가? 기차에서 돈 111원을 받았는데 이게 아니고 돈이 더 많아진 200원이란다. 살펴보니 차에서 받은 200원이 출력되었다. 상속받은 기차보다 확장시킨 차가 우선한다는 쇼킹한 부분이다. money 변수가 부모 자식 양쪽다 있어서 이런 일이 벌어지고 있는 것이다.ㅎㅎ 다음줄에 있는 t.ship( )을 실행해서 돈 300원을 받고 "자식만 배를 소유"라인을 찍는다. 다시 t.money(티머니?)를 확인한다. 가차없이 300원이다.^^

Child t2=new Child(m);
System.out.println(t2.money);//결과값 555

다음의 이 두라인은 같은 자식의 객체 생성이지만 기본 생성자가 아닌 m이라는 인자를 가진 생성자를 호출하는 예제이다. 뭐가 다른지 잘 살펴보기 바란다. 그럼 첫줄의 생성자가 있는 곳으로 가보겠다. m이 555니까 이 값을 받아줄 자식 생성자를 찾아보면 Child(int b)를 볼수 있을 것이다. 들어가서 돈 555원을 받고 "===인자 b가 있는 Child 생성자==="을 시키는데로 찍었다. 결과를 맞춰보니 이런? 앞에 한줄이 더 있다..- 부모 기본 생성자를 실행했다고 하는 출력결과가 있다. 어떻게 된일일까? ㅎㅎ

벌써 까먹었남? 필자가 얘기하지 않았던가 상속 관계에서 자식 생성자 안에 부모 생성자를 호출하는게 아무것도 없을때에는 자동적으로 super( ); 라는 부모 기본 생성자를 호출하라는 명령이 숨어있다고 말이다. 따라서 있는걸로 간주하고 부모 생성자를 호출한 것이다. 그래서 돈 2222를 받고 "===나는 Parent 기본 생성자==="를 찍고 나서 돈 555를 이때 받고 "===인자 b가 있는 Child 생성자==="를 출력한다. 부모 생성자 호출은 언제나 가장 처음에 이루어기 때문이다. 참 알아야 할것도 많다. 그치? ㅎㅎ

메인메소드로 돌아와서 티머니 아니 이제 티2머니(t2.money)를 찍으면 555가 찍힌다. 맨 마지막에 자식 money 변수의 돈 흐름은 거기에서 끝났으니까 당연하다. 여기서 분리선이 있는걸 보니 이제서야 첫번째 파트가 끝났다. ㅎㅎ 잠깐 쉬자~ 물도 먹고 스트레칭 하고 조금 후에 다시 만나자~ ^^

다 쉬었음 한번더 해보자. 파트 투우우~2 ^^
Parent t3=new Child( ); 여기서부터 할 차례인데 뭔가 심상치 않다. 객체 생성을 하는데 클래스 이름이 다르다(?) 이게 가능한가? 가능하다. 이래저래 상속은 어렵구나라고 실망하지 말자. 형태는 부모 클래스인 자식 클래스에 대한 레퍼런스 t3를 만들었는데 별 다른건 없다. 다만 t나 앞으로 만날 t5랑은 다른 레퍼런스 형태라는 것만 알아두기 바란다. 그걸로 족하니라.^^ 별 다를건 없고 new 키워드가 만들고 있는 자식 클래스 객체 생성자로 간다. 그럼 아까처럼 똑같이 실행한다.

1000
===인자 a가 있는 Parent 생성자===
부모는 자동차를 소유
이제는 자식도 자동차를 소유
자식만 배를 소유
100이 super.money값이다.
300이 this.money값이다.
===나는 Child 기본 생성자===

여기까지 똑같으니 이건 생략하고 다음줄부터 보겠다. t3.car( )랑 상속받았으니 t3.train( ) 메소드 다 실행가능하다. 따라서 "이제는 자식도 자동차를 소유"와 "부모는 기차를 소유"를 연달아서 처리한다. 그 다음 t3.ship( ); 실행하지 말라고 주석처리 해놓았는데 이거 보려고 이런 부모 자식 클래스의 다른 객체(?) 생성까지 한거다. 자식 메소드에 배(ship)가 있으니 당연히 될줄 알았겠지만 그렇지 않다. 에러다. 객체 생성시 형태는 부모 클래스로 만들고 인스턴스는 자식 클래스를 참조하게 만들면(Parent t3=new Child( );) 자식 클래스에게만 있는 이런 멤버는 접근할수가 없다. 멋들어지게 표현하자면 "부모의 자식 사랑은 끝이 없다고나 할까?" 오로지 주기만 할뿐 자식이 아니 자식 클래스가 가지고 있는 일반변수는 건드리지를 않는다. 이것은 자바의 다형성(Polymorphism)에 관련된 사항이다. 핵심만 설명하자면 부모클래스가 가지고 있는 일반변수만 사용가능하고 똑같은 메소드(오버라이드된 메소드)가 자식클래스에도 있을경우 자식클래스의 메소드를 호출하며 자식클래스에는 없는 메소드가 부모클래스에만 있을경우 부모클래스의 메소드를 호출한다. 둘다없는 경우는 당근 에러쥥.^^ 이런 형식은 객체생성을 할수 없는 추상클래스나 인터페이스의 경우에 많이 쓰인다.ㅎㅎ

다음에 Child t4=new Parent(); 라인이 나오는데 주석처리한 것처럼 실행불가능이다. 부모에서 자식으로는 객체 생성을 할수 있지만 반대로 자식에서 부모로는 객체 생성을 할수가 없다. 자식 클래스가 부모 클래스의 확장 발전된 형태이므로 이럴 경우 관계가 난감(?)해지기 때문에 안된다고 이해하면 될것이다. 또 한마디 해보자면, "자식은 부모에게 평생 제대로 효도 한번 못한다." 이런뜻과 일맥상통(?)이려나...^^ 이로써 파트2도 무사히 끝났다.ㅎㅎ 하나만 더 하자.

마지막 파트3에는 Parent t5=new Parent(); 부모 객체 생성을 통해 얻은 t5에 대한 설명이다. 당연히 부모 기본 생성자로 간다. 돈 2222로 받고 "===나는 Parent 기본 생성자==="를 찍는다. 부모 생성자안이니 여기서 자동으로 무슨 자식 생성자를 부른다거나 이런거 없다. "자식은 항상 부모의 보살핌을 필요로 하지만 부모는 그렇지 않다." 자식이 죄인이다.ㅎㅎ 그래서 생성자 호출끝내고 다시 메인메소드로 돌아와서 다음줄 t5.car( )와 t5.train( ) 메소드를 돈 100이랑 111받고 "부모는 자동차를 소유"랑 "부모는 기차를 소유"를 차례대로 출력한다. 부모 객체 생성했으니 당연히 부모만 보면 된다. 마지막에 t5.ship( )도 부모한테 이런거 없으니 당근 에러다. 당연히 안되는건데도 불구하고 이건지 아닌지 조심스러울거다. 이제껏 하도 당해놔서 말이다.ㅎㅎ

이제 예제풀이가 끝났다. 여러분의 소감은 어떤가? 상속이 그리 만만한 개념이 아니라고 느꼈을거라 본다. 거기다가 super라는 키워드가 끼어듦으로 인해서 말그대로 수퍼맨처럼 이리저리 다녀야하니 그대가 수퍼맨(?)이 되지 않고서는 자바의 상속이라는 개념을 제대로 이해하기 힘든 실정이다. 이번 강좌를 보면서 공부한 이들은 기존에 자바의 상속에 대해서 알고 있었을지라도 상당한 벽에 부딪치는 경험을 했을 것으로 생각한다. 프로그램이 방대해지면 방대해질수록 이런 미묘한 차이를 확실히 알지 못하면 디버깅 하는것조차 힘에겨워 할 것이다.

오늘은 super뿐만 아니라 그로 인해 생기는 자바 상속의 원리를 한 예제를 통해 집중조명하였다. 자바를 배우는 사람들의 절반 이상이 자바의 상속을 배우기 시작하면서부터 떨어져 나간다. 허나 강이와 함께 하는 여러분들은 승자까지는 아니더라도 살아남기만 하면 된다. 오늘 배운것처럼 부모의 원대하고 끝없는 사랑과 같이 여러분에 대한 강이의 사랑도 부모처럼 원없이 내리퍼주는 사랑(?)이기 때문이다.^^ 포기하지 말자. 계속 정진하면 언젠가 그 꿈은 반드시 이루어질 것이다. "Dream High!" ^^

댓글 19개:

  1. 정말 유익하게 보고 있습니다~
    감사합니다^^

    답글삭제
  2. 굉장히 재밌네요~ ㅋㅋㅋ
    지금 배우고 있는데 많이 유익하네요~
    감사합니다.

    답글삭제
  3. Woah! I'm really digging the template/theme of this website. It's
    simple, yet effective. A lot of times it's difficult to get that "perfect balance" between superb usability and visual appearance. I must say you've done a amazing job with this.

    Also, the blog loads super fast for me on Safari.
    Outstanding Blog!

    Check out my blog; car towing in panhandle
    my webpage: auto towing in panhandle

    답글삭제
  4. My spouse and I absolutely love your blog and find nearly all
    of your post's to be just what I'm looking for. Do you offer
    guest writers to write content in your case? I wouldn't mind creating a post or elaborating on some of the subjects you write in relation to here. Again, awesome website!

    my page :: loan signing agent in riverside

    답글삭제
  5. Remarkable! Its truly awesome piece of writing,
    I have got much clear idea concerning from this paragraph.


    Also visit my page; payroll services in edmonds

    답글삭제
  6. Hi to all, it's in fact a nice for me to pay a quick visit this web site, it consists of valuable Information.

    Feel free to visit my web page residential roofing contractor in oceanside

    답글삭제
  7. It is the best time to make some plans for the longer term
    and it is time to be happy. I've read this put up and if I may I desire to recommend you few interesting things or suggestions. Perhaps you can write next articles referring to this article. I want to learn more things about it!

    Also visit my page :: remodeling in sumner

    답글삭제
  8. Hey there! I've been following your site for a while now and finally got the courage to go ahead and give you a shout out from Houston Texas! Just wanted to say keep up the fantastic job!

    Also visit my web-site :: carpet installation in philadelphia

    답글삭제
  9. I'm pretty pleased to uncover this website. I need to to thank you for your time for this wonderful read!! I definitely enjoyed every part of it and I have you bookmarked to check out new stuff on your blog.

    Look at my weblog - pool repair in palm beach

    답글삭제
  10. Magnificent beat ! I wish to apprentice while you amend your website, how could i subscribe for a blog web site?
    The account helped me a acceptable deal. I had been a little bit
    acquainted of this your broadcast offered bright clear idea

    Have a look at my webpage: plumbing leaks in ann arbor

    답글삭제
  11. I truly love your site.. Excellent colors & theme.
    Did you create this web site yourself? Please reply back as I'm wanting to create my own blog and would like to find out where you got this from or just what the theme is called. Many thanks!

    Here is my web blog: hablo espanol notary in chula vista

    답글삭제
  12. Great blog! Do you have any hints for aspiring writers?
    I'm hoping to start my own blog soon but I'm a little lost on everything.

    Would you suggest starting with a free platform like Wordpress
    or go for a paid option? There are so many options out there that I'm completely overwhelmed .. Any suggestions? Bless you!

    my weblog ... notary in norco

    답글삭제
  13. I think this is one of the most vital information for me.
    And i'm glad reading your article. But wanna remark on some general things, The web site style is wonderful, the articles is really nice : D. Good job, cheers

    Here is my website - bathroom remodeling in des moines

    답글삭제
  14. I want to to thank you for this good read!! I absolutely loved
    every little bit of it. I've got you book-marked to look at new stuff you post…

    My web-site new cellulite treatment

    답글삭제
  15. 흩어져 있던 개념이 정리가 되는 군요..
    정말 감사합니다.!!

    답글삭제
  16. 감사합니다. 많이 배우고 갑니다

    답글삭제
  17. 부모는 자바나 실제나 위대하다.

    답글삭제