BackEnd/Java

[Java]다형성 (Polymorphism)

Hojung7 2024. 7. 31. 06:24

1. 다형성이란 ?

- 객체 지향 언어의 특징 중 하나로 ‘다양한 형태를 갖는다’라는 뜻으로

하나의 행동으로 여러 가지 일을 수행하는 개념.


- 상속을 이용한 기술로 부모 클래스 타입 참조변수 하나로

상속 관계에 있는 여러 타입의 자식 객체를 참조할 수 있는 기술

 

2. 클래스 형변환

업 캐스팅(Up Casting) (자식→ 부모) 다운 캐스팅(Down Casting) (부모→ 자식)
- "부모" 참조 변수 = '자식' 객체

- 참조하는 자식 객체가 부모 객체로 변함

* 부모로부터 상속받은 멤버만 참조 가능
ex)
Car  c = new Sonata();

→ Sonata 클래스는 Car 클래스의 후손

Sonata 클래스형에서 Car클래스형으로 바뀜
- 업 캐스팅 상태에서(부모 참조=자식 객체)

   참조 변수의 자료형을 자식 객체로 강제 형 변환하는 것

* 자동으로 처리되지 않기 때문에

반드시 자식 타입을 명시하여 형변환

* 반드시 상속 관계인 클래스 끼리만 형변환 가능
ex)
Car c = new Sonata();
((Sonata)c).moveSonata();

→ Sonata 클래스는 Car 클래스의 후손

Car 클래스형에서 Sonata클래스형으로 바뀜

 

#예제

[parent]

package pkg1.dto;

public class Parent {
	
	// 필드
	private String lastName = "김";
	private int money = 50000;
	
	// 기본 생성자
	public Parent() {
		super();  // 부모(Object) 생성자 호출
	}

	// 매개 변수 생성자(Alt + Shift + s -> o)
	public Parent(String lastName, int money) {
		super();
		this.lastName = lastName;
		this.money = money;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public int getMoney() {
		return money;
	}

	public void setMoney(int money) {
		this.money = money;
	}
	
	// toString() 오버라이딩
	@Override
	public String toString() {
		return "Parent : " + lastName + "/" + money;
		
	}
	
}

 

[Child]

package pkg1.dto;

// Parent 상속
public class Child extends Parent {
	
	private String car;
	
	public Child() {
	super();
}

	
	// 자식 객체 생성 시
	// 자식 + 부모 필드 한번에 초기화
	public Child(String lastName, int money, String car) {
		super(lastName, money);
		this.car = car;
	}
	
	public String getCar() {
		return car;
	}
	public void setCar(String car) {
		this.car = car;
	}
	
	// Parent의 toStrint() 오버라이딩 하기
	@Override
	public String toString() {
		return "Child : " + getLastName() + "/" 
				 + getMoney()      + "/"
				 +car;
	}
	
}

 

[Run1]

package pkg1.run;

import pkg1.dto.Child;
import pkg1.dto.Parent;

public class TestRun1 {
	public static void main(String[] args) {
		
		// 부모 참조 변수 = 부모 객체
		// -> 양쪽 다 Parent 타입
		//  == 컴퓨터 값 처리 원칙 잘 지켜짐!!!
		Parent p1 = new Parent();
		
		// 사용 가능한 필드/메서드 : Object, Parent
		System.out.println(p1.getLastName()); // Parent
		System.out.println(p1.hashCode());    // Object

 

#결과

[Run2]

		// 자식 참조 변수 = 자식 객체
		Child c1 = new Child();
		
		// 사용 가능한 필드/메서드 : Object, Parent, Child
		System.out.println(c1.hashCode());    // Object
		System.out.println(c1.getLastName()); // Parent
		System.out.println(c1.getCar());      // Child

 

#결과

[Run3]

		Parent p2 = new Child(); // 오류 안남!!!!
		
		// 사용 가능한 필드/메서드 : Object, Parent
		
		System.out.println( p2.hashCode() );    // Object
		System.out.println( p2.getLastName() ); // Parent
		
//		System.out.println( p2.getCar() ); 
		// -> Child 메서드 접근 불가!!!!

 

#결과

[Run4]

		Parent p3 = new Child(); // 업 캐스팅 상태
		
		// p3(Parent)를 Child로 강제 형변환 하여
		// 반환된 주소를 c3에 저장
		
		Child c3 = (Child)p3;
		
		// 아래 방법 처럼 필요할 때 마다 형변환 가능 하지만
		// 가독성이 떨어져 
		// 보통 자식 참조 변수에 대입해 사용!!
		// ((Child)p3).getCar();
		
		System.out.println(c3.getCar()); // 자식 메서드 참조 가능!

 

#결과