상속과 컴퍼지션

허성재's avatar
Aug 13, 2024
상속과 컴퍼지션
상속과 컴포지션(구성)은 객체 지향 프로그래밍에서 중요한 두 가지 설계 원칙입니다. 이 글에서는 상속과 다형성을 활용한 코드를 살펴보고, 이를 통해 이해할 수 있는 개념들을 자세하게 설명하겠습니다.

코드 설명: 상속과 다형성

먼저, 아래 코드를 통해 상속과 다형성에 대해 알아보겠습니다.
abstract class Car { // 추상 클래스 Car abstract void run(); // 추상 메서드 run } class Sonata extends Car { // Car 클래스를 상속받은 Sonata 클래스 @Override void run() { System.out.println("소나타 달린다"); } } class Genesis extends Car { // Car 클래스를 상속받은 Genesis 클래스 @Override void run() { System.out.println("제네시스 달린다"); } } public class Mem02 { public static void main(String[] args) { Car s = new Sonata(); // Sonata 객체를 Car 타입으로 생성 s.run(); // Sonata의 run() 메서드 호출 Car g = new Genesis(); // Genesis 객체를 Car 타입으로 생성 g.run(); // Genesis의 run() 메서드 호출 } }

1. 상속(Inheritance)

상속은 객체 지향 프로그래밍에서 기존 클래스를 기반으로 새로운 클래스를 정의하는 방법입니다. 여기서 Car 클래스는 추상 클래스(abstract class)로, SonataGenesis 클래스는 Car 클래스를 상속받아 각각의 기능을 정의합니다.
  • 추상 클래스(Car): 추상 클래스는 new 키워드를 사용해 인스턴스를 생성할 수 없습니다. Car 클래스는 추상 메서드 run()을 가지고 있으며, 이 메서드는 구체적인 동작이 정의되어 있지 않습니다. 대신, SonataGenesis 클래스가 이 메서드를 구체적으로 구현(override)하게 됩니다.
  • 구체 클래스(Sonata, Genesis): SonataGenesis 클래스는 Car 클래스를 상속받아 run() 메서드를 재정의(override)합니다. 이로써 각각의 클래스는 자신만의 동작을 가지게 됩니다.

2. 다형성(Polymorphism)

다형성은 동일한 인터페이스나 부모 클래스를 통해 다양한 객체를 다룰 수 있는 능력입니다. 여기서는 Car 타입의 변수가 SonataGenesis 객체를 참조할 수 있는 것이 다형성의 예입니다.
Car s = new Sonata(); Car g = new Genesis();
위 코드에서 Car 타입의 변수 sg는 각각 SonataGenesis 객체를 참조합니다. 다형성 덕분에 Car 타입으로 선언된 변수에 서로 다른 구체 클래스를 할당할 수 있습니다.
  • 동적 바인딩(Dynamic Binding): 메서드 호출이 런타임에 실제 객체의 타입에 따라 결정되는 것을 동적 바인딩이라고 합니다. 위 예제에서 s.run()을 호출할 때, Car 클래스의 run() 메서드를 호출하는 것이 아니라, Sonata 클래스에서 재정의된 run() 메서드가 호출됩니다. 이는 프로그램 실행 중에 s가 실제로 Sonata 객체를 참조하고 있기 때문입니다. 마찬가지로 g.run()Genesis 클래스의 run() 메서드를 호출합니다.

상속의 장점

  1. 코드 재사용: 공통된 기능을 부모 클래스에 정의하고, 이를 상속받아 재사용할 수 있습니다. 예를 들어, Car 클래스에 추가적인 공통 기능을 정의하면 SonataGenesis는 이를 자동으로 상속받게 됩니다.
  1. 유지보수성: 상속을 통해 변경이 필요할 때 부모 클래스만 수정하면 모든 자식 클래스에 적용되므로 코드 수정이 용이합니다.
  1. 다형성 활용: 부모 클래스 타입의 변수로 여러 자식 클래스를 다룰 수 있어 코드의 유연성이 높아집니다.
Share article

heo-gom