ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 다형성(Polymorphism)
    개발/자바JAVA 2024. 1. 31. 18:18

     : 수많은 모양을 가질 수 있는 성질.

     

    ※OOP(Object Oriented Programming) (객체지향 3대특징) : 캡슐화, 상속, 다형성

    ▶다형성 : 

     - '여러 개의 형태를 갖는다' 는 의미, 하나의 행동으로 여러 가지 일을 수행하는 개념이다.

     

     - 상속을 이용한 기술로 부모 타입으로부터 파생된 여러 가지 타입의 자식 객체를 

       부모 클래스 타입 하나로 다룰 수 있는 기술.

     

        -->즉,  "상속" 관계에 있는 클래스 타입간의 "형변환" 개념. 상속관계 아니면 안됨

     

           쉽게말해서  같은 이름의 메서드나 연산자가 다른 클래스에 대해 다른 동작을 하도록 하는 것.

     

     

    ※  다형성을 사용하는 이유

      1. 부모타입의 객체배열로 다양한 타입의 자식객체들을 받아줄 수 있기 때문.

          > 부모타입 하나만으로 다양한 자식 객체들을 다룰 수 있음

     

      2. 메소드의 매개변수나 반환형에 다형성을 적용하면  메소드의 갯수가 확 줄어든다.

     

     

    ◎다형성의 대표적은 예로는 오버라이딩(Overriding) 과 오버로딩(Overloading) 이있다.

     오버라이딩 : 슈퍼클래스를 상속 받은 서브 클래스에서 슈퍼 클래스의 메소드를 같은 이름, 같은 반환값, 같은 인자로 메소드 내의 로직들을 새롭게 정의하는 것을 말함.

     

    오버로딩 : 하나의 클래스에서 같은 이름의 메소드들을 여러 개 가질 수 있게 함. 단, 메서드 인자들은 달라야함.

     

     

    ◎예시를 통해 좀 더 쉽게 알아보자

     

     예시를 위해 다음과 같은 상속구조로 부모, 자식 클래스 들을 구성한다.

     

                                                                          상속구조

     

     

    부모 클래스인 Parent 클래스 는 x,y 인자를 가지고 있음

     

    자식 클래스인 Child 1, 2 클래스는 각각 z, n을 가지고 있는데 부모클래스에서 x,y 를 각각 상속받아

    Child1 : x,y,z    

    Child2 : x,y,n 을 가지고 있음.

     

     

     

     

     

     

     

    ● 각 부모, 자식 VO를 구성하고 (필드, 생성자, 메소드)

    부모 자식 클래스간 상속관계를 만들어준다.

     

     

     

     

    호출 관계를 이해하기 쉽도록

    Parent 클래스에 printParent( ) 출력용 메소드를 만들어주고

     

     

     

     child1클래스에 printChild1(_) 출력용 메소드

     

     

     

     

    child2 클래스에 printChild( ) 출력용 메소드를 만들어 준다.

     

     

     

     

     

    메인메소드를 통해 하나씩 알아보자!!

     

      먼저 비교를 위해 다형성이 적용되지 않은 경우부터 보면

       1. 부모 타입의 레퍼런스 (주소값 ==참조) 으로 부모 객체를 다루는 경우

       p1 레퍼런스로 Parent 타입에 접근이 가능하다. 

       일반적인 객체 생성 후 메서드 호출 한 경우이다.

    콘솔

     

        2. 자식 타입의 레퍼런스로 자식 객체를 다루는 경우.

     

    1번과 동일하지만, 특이사항이 있다면, 자식은 부모클래스의 메소드도 호출할 수 있다는 것이다.

     

        

    ● 다형성이 적용된 개념

       1. 부모타입 레퍼런스로 자식 객체를 다루는 경우

     

     

    Parent  p2 = (Parent) new Child1( );  // 자동형변환 된것이라 (Parent)가 생략되어있다.

    단, 상속관계 일때만 가능하다.  

    즉, 상속 구조에서는 클래스 타입간의 "형변환" 이 가능하다!!

     

     

     

    선언문만 봤을 때 p2는 Parent 타입이기 때문에 접근이 가능함!!

     

     

     그렇다면 자식타입 메소드로 접근해보면?

     

        

     

          부모타입 --> 자식타입으로 그냥 접근은 안된다...

     

     

        --->p2를 이용해서 그냥 자식타입 메소드에는 접근이 불가하다. 

              p2에 담겨있는 객체는 Child1타입으로 생성 후 Parent 타입으로 형변환 한 상태였음. Parent타입을 Child타입으로              형변환 한다면 접근이 가능함!! 

     

    즉, 부모타입 --> 자식타입 = 강제형변환 이 필요!!!!

     

    이런식으로 강제형변환을 해서 접근을 해야함.

     

     

       정리하자면

    ※상속 구조에서 클래스 간 형변환 가능 

    1. 자동형변환(UpCasting) : 자식타입 --> 부모타입

                           (형변환 연산자 생략가능)

     

    2. 강제형변환(DownCasting) : 부모타입 --> 자식타입

                           (형변환 연산자 생략 불가능(명시적 형변환))

     

     

        

       2. 객체배열 이용

     

      Child1 객체 2개, Child2 객체가 2개 필요한 상황이라고 가정하고, 객체 배열을 이용해 보자.

     

    ● 원래 배열은 이렇게 두개 씩 만들어야 한다.

     

    하지만, 다형성이 적용되면 부모타입의 레퍼런스로 자식타입을 다룰 수 있기 때문에

    Parent 레퍼런스로 Child1, Child2 를 함께 다룰 수 있다!!

     

    이렇게 말이다. 

    콘솔

     

    이렇게 다형성을 이용하면 같은 타입만 모아둘 수 있는 배열의 단점등을 보완하고 객체배열을 효율적으로 쓸 수 있다.

     

    ◆한가지 유의점은 

    Child1 타입이었던 arr[0] 를 Child2 타입으로 강제변환 해보면, 빨간줄은 안뜬다. 

    하지만 출력을 하면 오류가 발생한다.  이는 클래스 간의 형변환이 잘못 되었을 경우 인데.

     

    Child1 과 Child2 는 상속관계, 부모자식 관계가 아니기 때문에 형변환이 안되는 것이다.

     

    즉, 자식끼리는 상속이 안된다!! == 형변환이 안된다.

     

        3. instanceof 연산자

    위 배열을 for문을 이용해 한번에 출력해보자고 할때

     

     

    -배열 i 에 Child1 만 들어있지 않기 때문에 오류가 난다.

    그래서 각 배열에 주소값이 어떤 객체를 참조하고 있는지 각각 확인하고, 각 인덱스 별로 실제로 참조하고 있는 자식타입으로 다운캐스팅 후 자식메소드를 호출해야한다.

     

    이때, 각 배열에 주소값이 어떤 객체를 참조하는지는 instanceof 연산자로 확인할 수 있다.

     

    instanceof 연산자 : 현재 주소값이 실제로 어떤 자식 타입의 객체를 참고하고 있는지 확인할 수 있음.

     

    1.

    이런식으로 if문을 확용하여 각 객체마다 다운캐스팅 후 출력한다.

     

     

     

     아니면

     

      2. Override(재정의)를 이용해도 된다. 

          > 굳이 형변환 안해도, 형변환 전에 어떤 타입이었는지 검사조차 안해도 된다.

             오버라이딩 시 실질적으로 참조하고 있는 자식타입의 오버라이딩 된 메소드를 찾아가서 알아서 실행됨

              (오버라이딩 된 메소드가 더 우선순위가 높기 떄문)

     

     

    부모 클래스의 print( )메서드를 

     

     

     

    각 자식클래스마다 오버라이딩 한다.

     

     

     

     

     

     

     

     

    그리고 for 문에  메서드를 호출하면

     

     

     

     

     

     

     이렇게 제정의된 메서드 들이 호출된다!! 

     

     

     

     

     

    ※다형성은 객체지향 언어의 주요 3대 요소중 하나 이므로, 개념이 어려워도 반드시 확실하게 이해하고 넘어가야한다.

     

     

    '개발 > 자바JAVA' 카테고리의 다른 글

    기본API(Application Programming Interface)  (0) 2024.02.02
    추상클래스(Abstract Class)  (0) 2024.02.02
    상속(Inherit) / 오버라이딩(Overriding)  (1) 2024.01.30
    객체배열  (0) 2024.01.29
    메소드(Method) / 오버로딩(Overloading)  (1) 2024.01.29
Designed by Tistory.