CS

다형성

baek-dev 2025. 2. 16. 22:42

**다형성(Polymorphism)**은 같은 인터페이스나 부모 클래스를 공유하는 객체들이 각기 다른 방식으로 동작할 수 있는 성질을 의미함.

즉, 하나의 객체가 여러 형태를 가질 수 있는 능력을 말함.

📌 1. 다형성의 개념

다형성은 **객체지향 프로그래밍(OOP)**의 중요한 개념 중 하나로, 상속(Inheritance)과 인터페이스(Interface)를 활용하여 구현됨.

 

✅ 다형성의 핵심

1. 하나의 부모 클래스 또는 인터페이스를 기반으로 여러 자식 클래스가 서로 다른 동작을 가질 수 있음.

2. 컴파일 시점(정적 바인딩)과 실행 시점(동적 바인딩)에서 객체의 타입이 달라질 수 있음.

3. 코드를 유연하게 작성할 수 있으며, 유지보수성과 확장성이 증가함.

📌 2. 다형성의 종류

다형성은 크게 **“컴파일 타임 다형성”**과 **“런타임 다형성”**으로 나뉨.

 

🔹 (1) 컴파일 타임 다형성 (Compile-time Polymorphism) - 메서드 오버로딩

**메서드 오버로딩(Method Overloading)**을 활용하여 같은 이름의 메서드를 여러 개 정의할 수 있음.

컴파일러가 메서드의 매개변수를 보고 어떤 메서드를 호출할지 결정함.

 

예제 (Java)

class MathUtils {
    int add(int a, int b) {
        return a + b;
    }

    double add(double a, double b) {  // 같은 메서드 이름이지만 매개변수가 다름
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
        MathUtils math = new MathUtils();
        System.out.println(math.add(3, 5));       // 정수형 add 호출
        System.out.println(math.add(2.5, 4.5));   // 실수형 add 호출
    }
}

 

✅ 특징

메서드의 이름은 같지만 매개변수의 타입이나 개수가 다르면 다른 메서드로 인식됨.

컴파일 타임에 어떤 메서드를 호출할지 결정됨 (정적 바인딩).

🔹 (2) 런타임 다형성 (Runtime Polymorphism) - 메서드 오버라이딩

**메서드 오버라이딩(Method Overriding)**을 활용하여 부모 클래스의 메서드를 자식 클래스에서 재정의(Override)할 수 있음.

**동적 바인딩(Dynamic Binding)**을 통해 실행 시간에 어떤 메서드가 호출될지 결정됨.

 

예제 (Java)

class Animal {
    void makeSound() {
        System.out.println("동물이 소리를 냅니다.");
    }
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("멍멍!");
    }
}

class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("야옹!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Dog();  // 부모 타입으로 자식 객체 참조
        myAnimal.makeSound();  // 실행 결과: "멍멍!" (Dog의 메서드 호출)

        myAnimal = new Cat();
        myAnimal.makeSound();  // 실행 결과: "야옹!" (Cat의 메서드 호출)
    }
}

 

✅ 특징

부모 타입(Animal)으로 자식 객체(Dog, Cat)를 참조할 수 있음.

자식 클래스에서 부모 클래스의 메서드를 재정의(Override)하면, 실행 시점에 자식 클래스의 메서드가 호출됨.

실행 시점에 메서드가 결정되므로 “동적 바인딩”이 적용됨.

 

📌 3. 다형성의 활용

다형성은 객체지향 프로그래밍(OOP)에서 유연한 코드 작성을 위해 필수적인 개념이며, 다음과 같은 장점이 있음.

 

✅ (1) 코드의 재사용성 증가

부모 클래스를 정의해 두면, 새로운 기능이 필요할 때 자식 클래스를 만들고 메서드만 재정의하면 됨.

 

예제

class Employee {
    String name;

    Employee(String name) {
        this.name = name;
    }

    void work() {
        System.out.println(name + "이(가) 일합니다.");
    }
}

class Developer extends Employee {
    Developer(String name) {
        super(name);
    }

    @Override
    void work() {
        System.out.println(name + "이(가) 코딩합니다.");
    }
}

class Designer extends Employee {
    Designer(String name) {
        super(name);
    }

    @Override
    void work() {
        System.out.println(name + "이(가) 디자인합니다.");
    }
}

public class Main {
    public static void main(String[] args) {
        Employee dev = new Developer("철수");
        Employee des = new Designer("영희");

        dev.work(); // 철수가 코딩합니다.
        des.work(); // 영희가 디자인합니다.
    }
}

Employee 클래스를 상속받아 DeveloperDesigner 클래스를 생성하고, work() 메서드를 다형성으로 활용하여 다르게 동작하도록 구현함.

 

✅ (2) 인터페이스를 활용한 유연한 설계

다형성을 활용하면 인터페이스 기반으로 설계할 수 있음.

인터페이스를 구현하는 여러 클래스가 각기 다른 동작을 수행 가능.

 

예제

interface Vehicle {
    void move();
}

class Car implements Vehicle {
    @Override
    public void move() {
        System.out.println("자동차가 도로를 달립니다.");
    }
}

class Airplane implements Vehicle {
    @Override
    public void move() {
        System.out.println("비행기가 하늘을 납니다.");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle v1 = new Car();
        Vehicle v2 = new Airplane();

        v1.move(); // 자동차가 도로를 달립니다.
        v2.move(); // 비행기가 하늘을 납니다.
    }
}

Vehicle 인터페이스를 구현한 CarAirplane 클래스가 서로 다른 동작을 수행함.

코드 수정 없이 새로운 탈것을 추가할 수 있음 → 확장성이 뛰어남.

 

📌 4. 다형성을 사용할 때 주의할 점

1. 업캐스팅(Upcasting)과 다운캐스팅(Downcasting)

부모 타입으로 자식 객체를 참조하는 업캐스팅은 가능하지만, 다시 자식 타입으로 변환하려면 다운캐스팅을 해야 함.

다운캐스팅 시 instanceof 연산자로 타입을 체크해야 안전함.

Animal a = new Dog();
if (a instanceof Dog) {
    Dog d = (Dog) a;
    d.makeSound();
}

 

2. 오버라이딩 시 @Override 애노테이션 사용

실수로 메서드 이름을 다르게 적는 것을 방지할 수 있음.

 

3. 인터페이스를 적극 활용

상속보다 인터페이스를 활용한 다형성이 더 유연한 코드 작성에 유리함.

 

🚀 결론

**다형성(Polymorphism)**은 객체가 여러 형태를 가질 수 있는 성질로, **메서드 오버로딩(컴파일 타임)과 메서드 오버라이딩(런타임)**을 통해 구현됨.

객체지향 프로그래밍(OOP)에서 코드의 재사용성을 높이고, 유지보수성을 향상시키는 중요한 개념임.

인터페이스와 상속을 활용하여 다형성을 적용하면 유연한 설계가 가능함.

 

 

 

 

출처 : ChatGPT

'CS' 카테고리의 다른 글

락(Lock)과 동시성  (0) 2025.02.18
OCP 원칙 (Open-Closed Principle)  (0) 2025.02.17
DFS, BFS  (0) 2025.02.14
git branch 별 차이 (dev, origin dev, origin/dev)  (0) 2025.02.11
소프트딜리트 Soft Delete, 하드딜리트 Hard Delete  (1) 2025.02.08