자바 고급(JAVA)

객체지향 프로그래밍의 4가지 핵심 개념 - 다형성(Polymorphism)

beginner-development 2026. 5. 12. 23:34

1. 다형성이란?

  1. 영어로 poly(여러 개의) + morphism(형태)의 합성어로, 하나의 객체가 여러 형태를 가질 수 있는 성질을 의미한다.
  2. 자바에서의 다형성이란, 상위 클래스 타입의 참조 변수로 하위 클래스의 객체를 참조할 수 있는 성질을 말한다.
    • 다형성이 적용되면 참조 변수는 상위 클래스 타입이지만, 실제 호출되는 메서드는 오버라이딩된 하위 클래스의 메서드이다.

1 - 2. 다형성이 왜 필요할까?

  1. 여러 타입의 객체를 하나의 타입으로 관리가 가능하다.
  2. 같은 메시지로 다양한 객체를 처리가 가능하여 코드가 간결화되고 코드 유지보수가 쉬워진다.
  3. 새 객체가 생겨도 기존 메서드를 그대로 활용할 수 있어 확장에 유리하다.
  4. 의존성을 줄여 결합도를 낮추고 유연하고 유지보수하기 쉬운 설계가 가능하다.

1 - 3. 메서드 오버라이딩과 오버로딩

  1. 오버라이딩 (재정의)
    • 상속관계에서 부모 메서드를 자식 클래스에서 재정의
  2. 메서드 오버로딩 (중복정의)
    • 같은 이름, 다른 매개변수 형태의 메서드 다중 정의
    - 메서드 오버라이딩과 오버로딩도 다형성이다.

1 - 4. 다형성 정리

- 다형성은 객체지향 프로그래밍의 핵심 원리이다. 다양한 객체를 일관된 방식으로 다룰 수 있어 프로그램을 유연하고 확장성 있게 만들어 준다.

항목 설명
정의 하나의 타입(상위 타입)으로 여러 하위 타입 객체를 다룰 수 있는 특성
활용 기술 매서드 오버라이딩, 오버로딩, 업캐스팅
장점 확장성, 유지보수성, 코드 간결성, 결합도 감소
전제 조건 상속 또는 인터페이스 구현 관계

2. 참조 변수의 타입 변환(up-casting, down-casting)

- 자바에서는 기본형 변수뿐 아니라 참조 변수(객체)도 타입 변환이 가능하다. 참조 변수의 타입 변환은 "어떤 멤버(필드, 메서드)를 사용할 수 있는지를 제한 또는 확장"하는 개념으로, 이는 다형성을 제대로 이해하고 활용하기 위해 꼭 알아야할 기초 개념이다.

2 - 1. 타입 변환의 전제 조건

  1. 타입 변환은 반드시 상속 관계에 있는 클래스 사이에서만 가능하다.
  2. 상위 클래스 타입으로 변환 (업캐스팅)
    • 하위 클래스를 상위 클래스 타입으로 변환
    • 형 변환 연산자 생략 가능
    • 안전한 변환이며 대부분 자동으로 일어남
  3. 하위 클래스 타입으로 변환 (다운캐스팅)
    • 상위 클래스 타입의 참조 변수를 다시 하위 클래스 타입으로 변환
    • 형 변환 연산자 반드시 명시
    • 업캐스팅된 인스턴스에만 적용 가능

2 - 3. 다형성과의 연관

  1. 업캐스팅은 주로 다형성을 활용하기 위해 사용된다.
  2. 다형성 환경에서는 참조 변수의 타입에 따라 접근 가능한 멤버가 제한되며, 실제 객체의 기능을 사용하기 위해선 다운캐스팅이 필요할 수 있다.

2 - 4. 참조 변수의 타입 변환 정리

구분 업캐스팅(Up-casting) 다운캐스팅(Down-casting)
방향 하위 클래스 → 상위 클래스 상위 클래스 → 하위 클래스
형 변환 여부 묵시적 (형 변환 연산자 생략 가능) 명시적 (형 변환 연산자 반드시 필요)
사용 목적 다형성을 활용해 여러 하위 객체를 동일한 상위 타입으로 처리 상위 타입 참조 변수를 통해 하위 타입 고유 기능에 접근
안전성 안전 (컴파일, 런타임 모두 문제 없음) 위험 (잘못된 캐스팅 시 ClassCastException 발생 가능)
예시 Vehicle vehicle = new Car(); ((Car) vehicle).giveRide();
  1. 참조 변수의 타입 변환은 상속 관계를 전제로 한다.
  2. 업캐스팅은 묵시적으로 자동 변환되고, 다운캐스팅은 명시적으로 형 변환 연산자를 써야 한다.
  3. 다운캐스팅은 반드시 업캐스팅된 인스턴스에만 사용할 수 있으며, 그렇지 않으면 런타임 오류가 발생한다.
  4. 다형성을 활용하려면 업캐스팅을 통해 상위 타입으로 통일하고, 필요한 경우에만 다운캐스팅을 사용해 기능 확장을 할  수 있다.
  5. 타입 변환의 개념은 유연하고 확장성 있는 코드 구조를 설계하기 위한 중요한 기반이다.

3. instanceof 연산자

  - instanceof 연산자는 참조 변수의 타입 변환(캐스팅)이 가능한지 여부를 boolean 값으로 반환하는 자바의 연산자이다. 클래스의 상속 관계나 다형성이 복잡해질수록, 객체가 실제 어떤 타입의 인스턴스인지 코드 상에서 직접 파악하기 어려워지는데, 이때 instanceof를 통해 안전하게 형 변환 가능 여부를 판단할 수 있다.

3 - 1. 기본 문법

참조변수 instanceof 클래스명
  • 참조변수가 해당 클래스나 그 자식 클래스의 인스턴스라면 true를 반환한다.
  • 그렇지 않으면 false를 반환한다.
  • 참조 변수가 null이면 항상 false를 반환한다.

3 - 2. 예제 코드

public class InstanceOfExample {
       public static void main(String[] args) {
             Animal animal = new Animal();
             System.out.println(animal instanceof Object); // true
             System.out.println(animal instanceof Animal); // true
             System.out.println(animal instanceof Bat); // false
             
             Animal cat = new Cat();
             System.out.println(cat instanceof Object); // true
             System.out.println(cat instanceof Animal); // true
             System.out.println(cat instanceof Cat); // true
             System.out.println(cat instanceof Bat); // false
         }
}
class Animal {}
class Bat extends Animal {}
class Cat extends Animal {}

3 -3. 용도 및 필요성

  - 캐스팅 안전성 확보

    - 자바에서 상위 타입으로 선언된 참조 변수는 하위 객체를 가리킬 수 있지만, 다시 하위 타입으로 캐스팅할 때는형 변환 오류(ClassCastException)가 발생할 수 있다. 이때 instanceof를 이용하여, 캐스팅이 안전한지 검사한 뒤에만 타입 변환을 진행하면 오류를 예방할 수 있다.

  - 타입 안전성을 확보하는 구조

if (참조변수 instanceof 클래스명) {
    클래스명 변수명 = (클래스명) 참조변수;
      // 안전한 다운캐스팅 후 로직 수행
}

3 - 4. instanceof 연산자 정리

항목 설명
사용 목적 참조 변수의 실제 타입 확인 및 안전한 다운캐스팅 수행
반환값 boolean (true or false)
null 참조 검사 null instanceof 클래스는 항상 false
주의할 점 instanceof는 형변환 자체를 수행하지 않음,  단지 가능 여부만 판단함
주요 활용 케이스 다형성 상황에서 다운캐스팅이 필요할 때, 형변환 전에 안전성 확보

  - instanceof는 참조 변수가 어떤 타입인지 안전하게 판별하고, 형변환 전에 오류를 방지하기 위한 강력한 도구이다.

    ※ 이후 클래스가 많아지고 다형성이 복잡해질수록 instanceof의 활용도는 더욱 중요해진다. 실제 현업에서도 자주 등장하므로, 문법을 확실히 익혀두는것이 좋다.

4. 다형성의 장점

4 - 1. 중복 제거

  - 각 메서드 마다 할당된 중복된 메서드를 따로 만들 필요가 없다.

  - 상위 타입 하나로 공통 처리가 가능하다.

4 - 2. 유연한 확장

  - 새로운 객체가 추가될 경우에도, 기존 클래스는 수정 없이 그대로 사용할 수 있다.

5. 다형성 + 배열 활용

  - 아래 예제처럼 다양한 커피 객체를 배열에 담아 반복 처리할 수 있다. 이는 실제 실무에서 장바구니, 주문내역, 전략 패턴 등에 활용된다.

public class OrderBatch {
      public static void main(String[] args) {
            Coffee[] orderList = {
                   new Americano(),
                   new CaffeLatte(),
                   new Americano()
            };

          Customer customer = new Customer();
   
          for (Coffee coffee : orderList) {
                customer.buyCoffee(coffee);
          }

          System.out.println("최종 잔액: " + customer.money + "원");
      }
}

 

6. 다형성 마무리

  1. 다형성은 객체지향 프로그래밍에서 불필요한 중복을 줄이고, 유연한 확장을 가능하게 하는 핵심 개념이다.
  2. 특히 실무에서는 상품, 전략, 이벤트 처리 등 다양한 곳에서 다형성을 적극 활용한다.
  3. 매개변수 다형성, 배열 다형성, 인터페이스 기반 다형성까지 꾸준히 연습하며 익숙해지자.