[JAVA] 상속(inheritance)과 다형성(polymorphism)

Sia Hwang·2022년 11월 14일
0

JAVA

목록 보기
2/6

What it the Inheritance?

  • 상속이란 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것이다. 상속을 통해서 클래스를 작성하면 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있고 코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 매우 용이하다.

Why use the Inheritance?

  • 우리가 오리게임을 개발하게 되었는데 청둥오리와 물오리를 캐릭터로 만든다고 생각해 보자. 두 오리는 겉모습만 조금 다르지 기본적으로 같은 종족이기 때문에 공유하는 생물학적 특성이나 습성이 유사하다. 특히 꽥꽥 우는 행동은 청둥오리나 물오리나 똑같이 가지고 있다.
  • 그러면 청둥오리와 물오리 클래스를 만드는 과정에서 적어도 꽥꽥 우는 행동을 할 메서드는 두 클래스에서 비슷한 내용으로 구현하게 될 것이고, 이 과정에서 서로 유사하거나 같은 코드가 두 클래스에 작성될 것이다. 코드를 작성하다 보면 비슷한 내용은 보통 복붙을 하게 되기 때문에 결국 중복되는 코드가 생기게 된다.
  • 이 때 오리라는 이름을 가진 클래스를 만들어서 오리의 기본적인 행동을 할 메서드를 구현한 다음 청둥오리와 물오리 클래스에서 각각 상속받아 사용하게 하면 아까전에 생겼던 중복 코드를 줄일 수 있을 것이다.
  • 즉 기존의 클래스를 재사용 하는 과정에서 중복되는 코드를 줄일 수 있고 이후 유지보수시에도 공통적으로 사용되는 코드 한 부분만 수정하면 되기 때문에 매우 경제적이라 할 수 있다.

How to implement Inheritance?

  • 자바에서 상속을 구현하려면 extends 키워드를 사용하면 된다.
class Child extends Parent {
  // ...
}
  • 상속해주는 클래스를 부모 클래스, 상속받는 클래스를 자손 클래스라 한다.
  • 서로 상속관계에 있는 클래스를 다음과 같은 용어를 사용해서 표현하기도 한다.

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


[이미지 출처] http://www.tcpschool.com/java/java_inheritance_concept

  • 상속관계를 그림으로 나타내면 위와 같이 나타낼 수 있다.
  • 여기서 알 수 있는 것은 부모보다 부모를 상속받은 자손 클래스가 더 범위가 넓다는 것이다. 왜냐면 부모 클래스는 부모 클래스에서 정의한 멤버 변수와 메서드만 사용할 수 있지만 자손 클래스에서는 상속받은 부모 클래스의 멤버 변수와 메서드 외에 자손 클래스에서 사용할 추가적인 멤버 변수와 메서드를 정의하고 사용할 수 있기 때문이다.
  • 그래서 상속을 받는다는 것은 조상 클래스를 확장(extend)한다는 의미로 해석할 수도 있다. 이것이 상속에 사용되는 키워드가 extends인 이유이기도 하다.

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

Overriding

  • 자손 클래스에서는 상속받은 부모 클래스의 메서드의 내용을 재정의해서 사용할 수 있는데 이를 오버라이딩이라 한다.
  • 오버라이딩의 장점은 많지만 이 포스트에서 모두 쓰려면 길어지니까 별도의 포스트에 작성할 것이다.

Single Inheritance

  • C++에서는 여러 조상으로부터 상속받는 다중상속이 가능하지만 자바에서는 오직 단일상속만 허용한다.
  • 왜냐면 클래스 C가 클래스 A, 클래스 B 두 클래스를 모두 상속받았을 때 클래스 A와 클래스 B 모두에게 powerOn()이라는 메서드가 있다면 자손 클래스인 클래스 C에서는 어느 부모 클래스의 powerOn()을 상속받는 것인지 모호해지기 때문이다. 이름을 바꿔가면서 구별하는 것도 한계가 있고... 여러가지로 불편한 점이 많기 때문에 자바에서는 단일상속만 허용한다.
  • 그래서 클래스간의 관계가 명확해지고 코드를 더욱 신뢰할 수 있게 만들어준다는 점에서 다중상속보다 유리하다.

Object class

  • 자바에서 Object 클래스는 모든 클래스의 최상위에 있는 조상 클래스이다. 자바에서 사용되는 클래스들의 부모를 찾아찾아 거슬러 올라가면 마지막엔 Object 클래스가 있다. 그래서 toString()이나 equals()와 같은 메서드들을 따로 정의하지 않고 그냥 사용할 수 있다. 왜냐면 모두 Object 클래스에 정의되어 있기 때문이다.

What is the Polymorphism?

  • 상속과 함께 객체지향개념의 중요한 특징 중의 하나로, 여러 가지 형태를 가질 수 있는 능력을 의미한다.
  • 자바에서는 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함으로써 다형성을 프로그램적으로 구현하였다. 즉 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 하였다는 것이다.
class Parent {

}

class Child extends Parent {

}
  • 위와 같은 상속관계를 가지는 클래스들이 있다면
Parent P = new Child(); // 컴파일 잘 됨
  • 를 할 수 있는 것이다.
  • 이 경우에는 참조변수인 Parent에 정의된 멤버만 사용할 수 있는데 그 수가 자손 클래스인 Child에 정의된 멤버의 수보다 적기 때문에 없는 것을 사용할 위험은 없기 때문이다.
Child c = new Parent(); // 컴파일 에러
  • 하지만 반대 경우는 안 된다.

  • 왜냐면 상속받은 자식 클래스인 Child의 멤버 개수가 부모 클래스인 Parent보다 많기 때문에 Parent에 없는 멤버를 사용하려 할 수 있기 때문이다. 실제 내용물이 없는 것을 참조하면 당연히 NullPointerException이 발생할 것이다.

  • 이러한 특징은 메서드의 매개변수에도 적용해서 더욱 유연한 코드를 작성할 수 있다.

매개변수의 다형성

class Product {
  int price;
  int bonusPoint;
}

class Tv 	   extends Product {}
class Computer extends Product {}
class Audio	   extends Product {}

class Buyer {
  int money = 1000;
  int bonusPoint = 0;
}
  • 이러한 클래스가 있다고 할 때 Buyer 클래스에 물건을 구입하는 메서드를 추가하는 경우를 생각해 보자.
void buy(Tv t) {
  money -= t.price;
}
void buy(Computer c) {
  money -= c.price;
}
void buy(Audio a) {
  money -= a.price;
}
  • 매개변수에 다형성을 적용하지 않고 메서드를 만든다면 이렇게 만들 수 있을 것이다. 하지만 매개변수만 다를 뿐 결국 코드의 내용은 똑같다. 만약 구매 가능한 상품의 수가 늘어난다면 그만큼 buy() 메서드를 만들어줘야 한다. 여간 귀찮고 유지보수도 힘든 것이 아니다. 여기에 매개변수의 다형성을 적용하면 중복 코드를 줄이고 유지보수도 훨씬 쉬운 코드로 작성할 수 있다.
void buy(Product p) {
  money -= p.price;
}
  • 이렇게 쓰면 Product를 상속받는 모든 클래스들의 참조변수를 처리할 수 있다. 상품의 수가 늘어나도 문제가 없다.

  • 이것을 좀 더 확장해 보면 여러 종류의 객체를 배열에도 담을 수 있게 된다.

여러 종류의 객체를 배열로 다루기

  • 위에서 썼던 상품 클래스들을 다음과 같은 형태로 배열에 담을 수 있다.
Product p[] = new Product[3];
Product[0] = new Tv();
Product[1] = new Computer();
Product[2] = new Audio();
  • 이처럼 조상타입의 참조변수 배열을 사용하면, 공통의 조상을 가진 서로 다른 종류의 객체를 배열로 묶어서 다룰 수 있다. 또는 묶어서 다루고 싶은 객체들의 상속관계를 따져서 가장 가까운 공통조상 클래스 타입의 참조변수 배열을 생성해서 객체들을 저장하면 된다.

참고

profile
당면한 문제는 끝까지 해결하기 위해 노력하는 주니어 개발자입니다.

0개의 댓글