728x90
❓ 다형성(Polymorphism) 이란 ?

 

동일한 메시지(메서드 호출)에 대해 서로 다른 객체가 다르게 동작하는 능력(message pholymorphism)을 말합니다.
다형성은 한 가지 타입 또는 인터페이스를 여러 개의 구현체가 가질 수 있도록 함으로써 유연하고 확장 가능한 코드를 작성할 수 있게 합니다.

다형성은 상속과 관련하여 사용되며, 부모 클래스와 그 자식 클래스들 간에 동일한 메서드 이름을 가지고 있지만 각각의 클래스에서 다른 구현을 가지도록 하는 것을 의미합니다.
다형성은 같은 타입으로 선언된 객체가 실제로 실행 시에는 여러 다른 타입의 객체로 동작할 수 있게 합니다.

다형성은 다음과 같은 방식으로 구현됩니다:

  1. 업캐스팅(Upcasting): 자식 클래스의 인스턴스를 부모 클래스의 참조 변수로 참조하는 것을 말합니다. 부모 클래스의 참조 변수를 통해 자식 클래스의 객체에 접근할 수 있습니다. 업캐스팅을 통해 여러 개의 자식 클래스를 하나의 부모 클래스 타입으로 관리할 수 있습니다.
  2. 메서드 오버라이딩(Method Overriding): 자식 클래스에서 부모 클래스의 메서드를 재정의하여 자식 클래스에서 특화된 구현을 제공합니다. 부모 클래스의 메서드를 자식 클래스에서 동일한 이름으로 재정의하면, 실행 시에는 실제 객체의 타입에 맞는 메서드가 호출됩니다.
  3. 다형적 변수(Polymorphic Variables): 부모 클래스의 참조 변수를 사용하여 여러 자식 클래스의 객체를 참조할 수 있습니다. 이렇게 다형적 변수를 사용하면 실행 시에 실제 객체의 타입에 따라 다른 동작을 수행할 수 있습니다.

다형성은 코드의 유연성과 재사용성을 높여주며, 객체 지향 프로그래밍의 핵심 원칙 중 하나인 "프로그램을 작성할 때는 구체적인 타입보다는 추상적인 타입에 의존하라(Depend upon abstractions)"를 실현하는 방법 중 하나입니다.

 

https://kadosholy.tistory.com/99

 

 

        //Cat 클래스 (자식)
        public class Cat extends Animal {
                public void eat() {
                    System.out.println("고양이처럼 밥 먹는다");
                }
        }

        //Dog 클래스 (자식)
        public class Dog extends Animal{

            public void eat() {
                System.out.println("강아지처럼 먹어보자");
            }
        }

        //Animal 클래스 (부모)
        public class Animal {
            public void eat() {
                System.out.println("동물처럼 먹다");
            }
        }

        //Override 클래스 (메인)
        public static void main(String[] args) {
        /*
        Upcastiong(업캐스팅) -> 만약 다른 사람이 Dog클래스를 java 소스코드를 주지 않고, 
        class 파일만 주었을 때, Dog 클래스로 선언하기 어려움

        Animal <---> Dog.class(o) Animal 클래스가 Dog클래스와 상속관계에 있다는 것을 
        알고있다는 가정하에 Override 통해 eat()을 재 정의 할 수 있게 됩니다.
        */
                Animal ani = new Dog();
                ani.eat();
        // Animal ----실행시점에서 메서드가 결정되는 것(동적바인딩)---> Dog
        // 작성 시에는 eat()가 Animal에 속해있는 것이라고 생각되어 에러가 나지 않았지만, 실행과 동시에 Dog의 eat()이 실행되게 됩니다 / 이를 동적바인딩이라고 합니다.
                System.out.println("ani = " + ani);
            }
        }

앞서 업캐스팅과 동적바인딩을 설명할 때 , 사용했던 코드로 다형성을 설명해보면, 부모클래스 (Animal)이 먹다(eat())
메서드를 자식클래스인 Dog와 Cat에게 메세지를 보내면 자식 클래스가 반응을 하는데, 두 자식 클래스에서 eat() 메서드가 개와 고양이로 다르기 때문에 서로 다르게 반응을 하게 됩니다.

다형성을 적용하기 위해서는 Upcasting으로 객체를 생성 상속 관계로 되어 있어야 하며, 재 정의가 되어있고, 메모리에서 동적 바인딩이 되어있는 관계여야 가능하다.
상위클래스가 동일한 메세지로 하위 클래스를 서로 다르게 동작시키는 객체지향 원리 (=message polymorphism)

컴파일 시점에선 eat()가 Animal내의 eat() , 실행시점에서 호출될 메서드가 결정되는 바인딩 = 동적바인딩
-> 동적바인딩이 일어나야 eat()라는 메서드가 Animal것인지 Dog것인지 알 수 있다.

 

💡 다형성(message polymorphism)의 전제조건

1. 상속관계    2. Override(재정의)    3. Upcasting(업캐스팅)   4. 동적 바인딩

 

💡 다형성 활용 - 다형성 인수란 ?

다형성 인수(Polymorphic Parameters)란, 메서드나 함수의 매개변수(parameter)를 다형성(polymorphism)을 활용하여 여러 타입의 객체를 전달할 수 있는 것을 말합니다. 이를 통해 코드의 재사용성과 유연성을 높일 수 있습니다.

 

        public void makeShape(Shape shape) {
            // 도형을 처리하는 로직
            shape.draw();
        }

        Circle circle = new Circle();
        Triangle triangle = new Triangle();
        Rectangle rectangle = new Rectangle();

        makeShape(circle);     // Circle 객체 전달
        makeShape(triangle);   // Triangle 객체 전달
        makeShape(rectangle);  // Rectangle 객체 전달

 

위의 코드에서 makeShape 메서드는 Shape 타입의 매개변수 shape를 받습니다. 이 매개변수는 다형성 인수로, Shape 클래스를 상속한 여러 도형 클래스의 인스턴스를 전달할 수 있습니다. 예를 들면, Circle, Triangle, Rectangle 클래스가 Shape 클래스를 상속한다고 가정해보겠습니다.

위의 코드에서 makeShape 메서드에 각각의 도형 객체를 전달하고 있습니다. 이 때, 전달되는 객체는 각자의 실제 타입인 Circle, Triangle, Rectangle 이지만, 메서드 내부에서는 Shape 타입으로 참조되고 처리됩니다. 이는 다형성의 개념을 활용한 예시로서, 동일한 메서드를 여러 타입의 객체에 대해 재사용할 수 있음을 보여줍니다.

다형성 인수는 코드의 유연성과 확장성을 제공하며, 객체지향 프로그래밍에서 중요한 개념 중 하나입니다.

instanceof 연산자 : instanceof 연산자는 객체의 타입을 확인하기 위해 사용되는 연산자 사용 문법
[객체] instanceof [타입]

instanceof를 사용하여 특정 객체가 특정 클래스의 인스턴스인지를 확인할 수 있습니다.

        Shape shape = new Circle();

        if (shape instanceof Circle) {
            System.out.println("shape은 Circle의 인스턴스입니다.");
        } else if (shape instanceof Rectangle) {
            System.out.println("shape은 Rectangle의 인스턴스입니다.");
        } else {
            System.out.println("shape은 Circle 또는 Rectangle의 인스턴스가 아닙니다.");
        }


위의 코드에서 makeShape 메서드는 Shape 타입의 매개변수 shape를 받고, shape 객체의 타입을 instanceof 연산자를 사용하여 확인합니다. 이후 해당하는 타입으로 캐스팅하여 각각의 타입에 맞는 처리 로직을 수행합니다. instanceof 연산자는 주어진 객체가 해당 타입의 인스턴스인지를 불리언(Boolean) 값으로 반환합니다. 만약 객체가 해당 타입의 인스턴스이면 true를 반환하고, 그렇지 않으면 false를 반환합니다.

instanceof 연산자는 객체의 상속 관계나 인터페이스 구현 여부를 확인할 때 주로 사용됩니다. 타입 검사를 통해 객체의 동적인 타입을 파악하여 적절한 동작을 수행할 수 있습니다. 다형성과 함께 사용하면 유연하고 확장 가능한 코드를 작성할 수 있습니다.

💡 다형성 활용 - 다형성 배열(상위타입 배열)이란?

 

다형성배열이란 ? 다형성 개념을 배열에 적용한 것을 의미합니다. 성 배열은 여러 타입(서로 다른 타입)의 객체를 하나의 배열에 저장할 수 있는 특징을 갖고 있습니다.

일반적으로 배열은 동일한 타입의 객체들만 저장할 수 있지만, 다형성 배열은 부모 클래스를 상속받은 서브 클래스들을 모두 저장할 수 있습니다. 이를 통해 서로 다른 타입의 객체를 하나의 배열에 함께 저장하고 관리할 수 있습니다. 부모클래스 타입의 배열은 자식클래스 타입을 저장하는 것이 가능합니다.

728x90
반응형

+ Recent posts