본문 바로가기

프로그래밍/JAVA

[JAVA] 상속(Inheritance)

JAVA의 정석(2nd Editionm) (남궁 성 著) 222p~237p 를 참조해 코드를 작성했으며


개인적인 공부 내용을 적은 것이므로 오류가 있을 수 있습니다.


0. 들어가기에 앞서



    유교 문화의 관점에서 "부모가 자식보다 더 큰 존재다."라고 한다면 왼쪽 그림이 맞을 것이다.

하지만 자바에서는 그렇지 않다. Child는 Parent의 재능(인스턴스)을 상속받아 더 많은 활동을 할 수 있다.


만약 부모가 talk, calculate, draw라는 메서드를 가지고 있다면, 고스란히 자식도 그 기능을 사용할 수 있다.

따라서, 자손 클래스는 항상 조상 클래스보다 같거나 많은 멤버를 갖게 된다.


조상 클래스 - 부모(parent) 클래스, 상위(super) 클래스, 기반(base)클래스

자손 클래스 - 자식(child) 클래스, 하위(sub) 클래스, 파생/유도(derived) 클래스 


조상 클래스 대신 상위 클래스라는 말을 자주 사용하니, 내용을 숙지하자.

자손 클래스 대신 하위 클래스라는 말을 자주 사용하니, 내용을 숙지하자.



[ 참 고 ]

안드로이드에서는 이러한 상속관계를 자주 사용한다.

이렇게 AddInterface라는 서브 클래스는 AppCompatActivity라는 슈퍼클래스의 기능들을 상속받는다.



1. 상속의 정의와 장점


상속 : 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것


장점 : 코드의 재사용성을 높여 프로그램의 생산성과 유지보수에 크게 기여한다.


단, 생성자와 초기화 블럭은 상속되지 않고, 멤버(변수+메서드)만 상속된다.

자손 클래스의 멤버 개수 >= 조상 클래스의 멤버 개수


만약 슈퍼 클래스에서 접근 지정자가 private로 선언되어 있으면 

서브 클래스에서는 사용이 불가능하다.


반면에 다른 클래스에서는 접근이 불가능하지만 슈퍼클래스와 서브클래스만 사용할 수 있는

접근 지정자도 있다. 그것은 바로 protected이다.


위 문장을 무리 없이 이해할 수 있겠는가?


class Parent { int age; }
class Child extends Parent { }

이런 식으로 써준다면 자손 클래스는 조상 클래스의 모든 멤버를 상속받는다.

(단, 생성자와 초기화 블럭은 상속되지 않으며, 항상 멤버만 상속된다.)



좀 더 복잡한 상속관계를 만들어보자.


class Parent { int age; }
class Child1 extends Parent { }
class Child2 extends Parent { }
class GrandChild extends Child { }




2. 클래스간의 관계 - 포함관계 및 관계 결정하기


상속을 통해 코드를 재사용할 수도 있지만, 포함(Composite) 관계를 통해서도 재사용이 가능하다.


class Point { int x, int y } 가 있다고 가정을 해보자. 

기존 Circle 클래스에 int x와 int y를 Point 클래스의 멤버변수로 선언할 수 있다.


그렇다면 언제 상속(extends)를 써야 하고, 언제 포함(Composite)를 써야 할까?


   상속(extends)  관계 - '~은 ~이다. (is a)'

포함(implements)관계 - '~은 ~을 가지고 있다. (has a)'


로 구분해주면 된다.


    원은 점(is a)일까? 

원은 점을 가지고(has a) 있을까? 후자가 맞을 것이다.


따라서 "포함 관계"가 더 적절하다.


스포츠 자동차는 자동차(is a)일까? 

스포츠 자동차는 자동차(has a)를 가지고 있을까? 전자가 맞을 것이다.


따라서 "상속 관계"가 더 적절하다.



Parent name = new Child ( );

TV samsung = new AmoledTV ( );

  그러면 위와 같이 Parent타입의 참조변수로 Child 클래스의 인스턴스(변수+메서드) 참조가 가능할까?

  어색해보일지 몰라도 가능하다.




3. 메서드 오버라이딩


오버라이딩을 잘 모르겠다면 http://whatisthenext.tistory.com/22 (ctrl+클릭)을 참고하자


  하위 클래스에서 메소드를 다시 정의하면 어떠한 일이 벌어질까?

  위 코드를 보면 부모는 "나는 말을 할 줄 알지"라는 메서드를 가지고 있고

  자식은 이를 오버라이딩해 한국말은 더불어 영어까지 할줄 알게 된다.


  메인메서드에서 Child타입의 a 참조변수를 이용해 talk메서드를 부른다.

  그러면 당연히 Child 클래스에서 "새롭게 정의한(over-riding)" talk 메서드가 작동되는 것을 볼 수 있다.

  여기서 super.talk()가 상위 클래스의 메서드를 호출하고 있다.


  즉, 자식 클래스에서는 2개의 talk 메서드를 가지고 있다. 

  Child타입의 참조변수(a)를 통해 접근하는 메서드는 Child에 정의된 메서드 하나 뿐이다.

 

4. 단일상속(Single Inheritance)


자바에서는 하나 이상의 클래스로부터 상속을 받을 수 없다.

(Ex : class C extends A, B와 같은 표현은 허용되지 않는다.)


TVCR은 TV를 상속받기는 했지만 VCR클래스의 인스턴스를 생성해서 사용할 수 있다.


5. Object클래스 (모든 클래스의 조상)


우리는 class TV의 코드를 컴파일하면 컴파일러는 자동으로 extends Object를 추가한다.

사실상 이 생략되어 있던 것으로 보면 된다.


toString() 이나 equals(Object o)와 같은 메서드를 따로 정의하지 않고도 사용할 수 있었던 이유는

이 메서드들이 Object 클래스에 정의된 것들이기 때문이다.