-
다형성(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