자바[JAVA] : 상속의 특징

2021. 1. 28. 02:42Java

반응형

● 자바 상속의 특징

 상속이란? 

- 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것. 상속을 통해서 클래스를 작성하면 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있고 코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 매우 용이하다. 코드의 재사용성을 높이고 코드의 중복을 제거하여 생산성과 유지보수에 크게 기여.

 

 상속을 구현하는 방법 

- 새로 작성하고자 하는 클래스의 이름뒤에 상속받고자 하는 클래스의 이름을 키워드 'extends'와 함께 써 주기만 하면 된다.

 class Child extends Parent {
 	//...
 }

- 새로 만드는 클래스는 Child이고 기존 클래스는 Parent이다. 이 두 클래스는 서로 상속 관계에 있다고 하며, 상속해주는 클래스를 '조상 클래스(Parent)'라 하고 상속받는 클래스를 '자손 클래스(Chile)'라 한다.

  • 조상 클래스 : 부모(parent)클래스, 상위(super)클래스, 기반(base)클래스
  • 자손 클래스 : 자식(child)클래스, 하위(sub)클래스, 파생된(derived)클래스

- 아래외 같이 서로 상속관계에 있는 두 클래스를 그림으로 표현하면 다음과 같다.

class Parent { }
class Child extends Parent { }

자손 클래스는 조상 클래스의 모든 멤버를 상속받기 때문에, Child클래스는 Parent클래스의 멤버들을 포함한다고 할 수 있다.

만일 Parent클래스에 age라는 정수형 변수를 멤버변수로 추가하면, 자손 클래스는 조상의 멤버를 모두 상속받기 때문에, Child클래스는 자동적으로 age라는 멤버변수가 추가된것과 같은 효과를 얻는다.

class Parent {
    int age;
}

class Childe extends Parent {  }

반대로 자손 클래스에 새로운 무언가가 추가되어도 조상 클래스에는 아무런 영향을 주지 않는다.

class Parent {
    int age;
}

class Child extends Parent {
    void play() {
        System.out.println("하이");
    }
}

자손 Child클래스에 새로운 멤버로 play() 메서드를 추가.

 자손 클래스는 조상 클래스의 모든 멤버를 상속받으므로 항상 조상클래스보다 같거나 많은 멤버를 가진다. 즉, 상속을 거듭할수록 상속받는 클래스의 멤버 개수는 점점 늘어나게 된다.

상속을 받는다는 것은 조상 클래스를 확장(extends)한다는 의미로 해석할 수도 있으며 상속에 사용되는 키워드가 ‘extends’인 이유이기도 하다.

  • 생성자와 초기화 블럭은 상속되지 않는다. 멤버만 상속된다.
  • 자손 클래스의 멤버 개수는 항상 조상 클래스보다 같거나 많다.

 

 다수의 자손을 구현 

다음과 같이 하나의 조상클래스와 다수의 자손 클래스가 있다.

class Parent {  }
class Child  extends Parent {  }
class child2 extends Parent {   }

클래스 Child1과 Child2가 모두 Parent클래스를 상속받고 있으므로 Parent와 Child1, Parent와 Child2는 서로 상속관계에 있지만, 자손 클래스 간에는 아무런 관계도 성립하지 않는다. 클래스 간의 관계에서 형제 관계와 같은 것은 없다.

만일 child클래스와 child2클래스에 공통적으로 추가되어야 하는 멤버(멤버변수나 메서드)가 있다면, 이 두 클래스에 각각 따로 추가해주는 것보다는 이들의 공통 조상인 Parent클래스에 추가하는 것이 좋다.

여기에 또다시 Child클래스로부터 상속받는 GrandChild라는 새로운 클래스를 추가한다면 상속계층도는 다음과 같을 것이다.

class Parent { }
class Child1 extends Parent { }
class Child2 extends Parent { }
class GrandChild extends Child1 { }

자손 클래스는 조상 클래스의 모든 멤버를 물려받으므로 GrandChild 클래스는 Child1 클래스의 모든 멤버와 Parent 클래스로부터 상속받은 멤버까지 상속받게 된다. 즉, GrandChild 클래스는 Parent 클래스와 간접적인 상속관계를 가지게 된다.

 

 클래스간의 관계 - 포함관계 

상속 이외에도 클래스를 재사용하는 또 다른 방법이 있는데, 그것은 클래스간에 '포함(Composite)'관계를 맺어 주는 것이다. 클래스간의 포함관계를 맺어 주는 것은 한 클래스의 멤버변수로 다른 클래스 타입의 참조변수를 선언하는 것을 뜻한다.

원을 표현하기 위한 Circle이라는 클래스와, 좌표상의 한 점을 다루기 위한 Point클래스가 작성되었다고 하자.

class Circle {
    int x;  //원점의 x좌표
    int y;  //원점의 y좌표
    int r;  //반지름
}

class Point {
    int x; //x좌표
    int y; //y좌표
}

Point 클래스를 재사용해서 Circle클래스를 다시 작성한다면 다음과 같이 할 수 있다.

class Circle {
    Point c = new Point();
    int r;
}

- 이와 같이 한 클래스를 작성하는 데 다른 클래스를 멤버변수로 선언하여 포함시키는 것은 좋은생각이다. 하나의 거대한 클래스를 작성하는 것보다 단위별로 여러개의 클래스를 작성한 다음, 이 단위 클래스들을 포함관계로 재사용하면 보다 간결하고 손쉽게 클래스를 작성할 수 있다. (공통으로 쓰이는것들은 이런 식으로 포함관계 방법을 사용하면 재사용에 아주 유용함으로 습관을 들이자!!)

그렇다면 상속관계와 포함관계를 결정하기 위해서는 어떻게 선택을 할까?

  • 원(Circle)은 점(Point)이다. - Circle is a Point.
  • 원(Circle)은 점(Point)을 가지고 있다. - Circle has a Point.

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

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

-> 프로그램의 모든 클래스를 분석하여 가능한 많은 관계를 맺도록 노력해서 코드의 재사용성을 높이자!!

 

단일 상속(single inheritance)

다른 객체지향언어인 C++ 에서는 여러 조상 클래스로부터 상속받는 것이 가능한 '다중상속'을 허용하지만 자바에서는 오직 단일 상속만을 허용한다.

class Child extends Father, Mother {
    //... 에러. 조상은 하나만 허용한다.
}

다중상속을 허용하면 여러 클래스로부터 상속받을 수 있기 때문에 복합적인 기능을 가진 클래스를 쉽게 작성할 수 있다는 장점이 있지만, 클래스간의 관계가 매우 복잡해진다는 것과 서로 다른 클래스로부터 상속받은 멤버간의 이름이 같은 경우 구별할 수 있는 방법이 없다는 단점을 가지고 있다.

자바에서는 다중상속의 이러한 문제점을 해결하기 위해 다중상속의 장점을 포기하고 단일상속만을 허용한다.

출처 : 자바의 정석

반응형