Notice
Recent Posts
Recent Comments
관리 메뉴

Developer Gonie

[2주차] 47. 다형성, 자식객체들을 부모타입의 참조변수로 한 번에 관리, 매개변수도 부모타입 하나로 자식객체들을 모두 받기가능* 본문

K-DigitalTraining 강의/1. Java

[2주차] 47. 다형성, 자식객체들을 부모타입의 참조변수로 한 번에 관리, 매개변수도 부모타입 하나로 자식객체들을 모두 받기가능*

이대곤 2022. 5. 26. 15:14

* 다형성이란?

다형성은 어느 특정한 요소가 다양한 자료형에 속할 수 있는 성질을 말한다. 프로그래밍 언어가 이 성질을 구현해 낼 수 있도록 지원한다면, 중복되는 코드의 양을 줄일 수 있게 된다. 다형성이 존재한다면 하나의 참조변수로 다양한 타입의 객체들을 다루는 것이 가능해지는데 이를 이용하면 코드 작성이 더욱 간략해진다. 혹은 공통 특성으로 타입을 추상화하면 하나의 코드로 여러 타입의 객체를 다룰 수 있게 된다고 말 할 수 있겠다.

 

자바는 다형성이 가능해지도록 자식클래스 객체의 참조변수가 부모클래스의 타입으로 변환되는 것을 허용하는데, 이는 상속 관계일 때만 가능하다. 자바에서의 다형성을 이용한 한가지 예시로 Parent 클래스의 참조변수가 Child 클래스 객체의 주소를 가리키고 있는 경우가 있다. 물론 이 과정에서 Child 클래스의 객체는 Parent 클래스의 타입으로 형변환된다. 아래 예제의 클래스들을 이용해 예시를 들면 다음과 같은 형태가 가능하다. (FireEngine클래스는 Car의 자식클래스)

Car c = new FireEngine(); // Car c = (Car)new FireEngine(); 형변환이 자동으로 이뤄짐

 

자식클래스 타입의 것을 부모클래스 타입에 할당할 경우 자동으로 부모클래스 타입으로 형변환 되는데 이를 '업캐스팅'이라고 하며, double d = 4에서 double d = (double)4 이 자동으로 되는 것과 비슷하다. 반대의 경우로 다운캐스팅이 존재하는데, 이것이 정상작동 하려면 다운캐스팅 되기전 업캐스팅이 이뤄진 상태이어야 한다. 이 때문에 아래와 같이 instanceof 를 사용하여 참조변수가 다운캐스팅 하려는 객체를 가리키고 있는지 체크한다. 또한, 다운캐스팅의 경우 자동형변환이 수행되지 않기 때문에 형변환을 명시해줘야 한다. 

 

<업캐스팅 이후 발생하는 제약조건>

- 접근 가능한 멤버는 부모 클래스의 멤버변수 및 멤버함수로만 한정된다.

   단, 예외가 있는데 메소드가 자식 클래스에서 오버라이딩 되었다면 자식 클래스의 메소드가 호출된다.

   멤버변수는 자식에서 재선언 했다고 하더라도 접근불가.

 

자식클래스 객체의 참조변수가 부모클래스 타입으로 자동 타입 변환된 이후에도 같은주소 즉 자식 객체를 참조하지만, 접근 가능한 멤버는 부모 클래스의 멤버변수 및 멤버함수로만 한정된다. 단, 예외가 있는데 메소드가 자식 클래스에서 오버라이딩 되었다면 자식 클래스의 메소드가 호출된다. 이것이 타입은 같지만 객체에 따라서 실행 결과가 다양해질 수 있는 요인이다.

 

다형성을 이용하면 조상클래스 타입의 배열로 선언한 참조변수 하나로 자손들의 객체를 모두 묶어 한 번에 관리할 수 있다. 배열이라면 원래 같은 타입만 다뤘던걸 기억하는가? (int [] arr = {1, 2, 3)) 다형성은 이를 좀 더 확장시키기 위한 느낌이라 할 수 있겠다.

 

* 업캐스팅이란?

특정 객체가 자손클래스 타입에서 조상클래스 타입으로 캐스팅 되는것

다형성이 적용된 예시코드1

class Car {
	String color = "white";
	int door = 4;

	void drive() {
		System.out.println("drive");
	}

	void stop() {
		System.out.println("stop");
	}
}

class FireEngine extends Car {
	int door = 6;
	int wheel = 10;

	void drive() { // 오버라이딩
		System.out.println("more fast drive~");
	}

	void water() {
		System.out.println("water~");
	}
}

public class Ex07_연습 {
	public static void main(String[] args) {

		Car c = new Car(); // 부모클래스의 객체생성
		FireEngine f = new FireEngine(); // 자식클래스의 객체생성

		/*업캐스팅*/
		c = f; // c = (Car)f; 와 같음		
//		부모클래스 타입의 참조변수 c가 자식클래스 타입의 참조변수 f가 가리키는 주소를 넘겨받으며 따로 명시해주지 않아도 f는 부모클래스 타입으로
//		자동형변환 됨 "c = (Car)f" 이를 업캐스팅이라고 한다. 조상클래스의 타입으로 자손클래스가 형변환되기 때문이다.
//		이 현상은 마치 int형 정수를 double형 변수에 할당시 double형으로 자동형변환 되는 것과 같음.
//		 

		// 부모클래스의 멤버변수 및 멤버함수 정상접근 가능
		System.out.println(c.color);
		System.out.println(c.door);
		c.stop();
		System.out.println();

		// drive()메서드는 제한사항에 의해 자식클래스에서 오버라이딩 했기 때문에 자식의 것이 호출됨
		c.drive();
		System.out.println();

		// 접근불가 부분
		//System.out.println(c.wheel);
		//System.out.println(c.water);
		
		/*다운캐스팅시도*/
		if(c instanceof FireEngine) { //c가 Car클래스 타입의 참조변수이지만 FireEngine 객체를 가리키고 있는가?
			System.out.println("다운캐스팅 가능");
			f = (FireEngine)c; // 업캐스팅을 했어야 다운캐스팅이 가능함. 그리고 다운캐스팅은 형변환을 명시해줘야 함.
	
			System.out.println(f.door);
			System.out.println(f.wheel);
			System.out.println(f.color);
			f.drive();
			f.water();
			f.stop();
		}else {
			System.out.println("다운캐스팅 불가능");
		}
	}
}

실행결과

white
4
stop

more fast drive~

다운캐스팅 가능
6
10
white
more fast drive~
water~
stop

다형성이 적용된 예시코드2

class Product {
	String code;
	String company;

	Product(String code, String company) {
		this.code = code;
		this.company = company;
	}

	void show() {
		System.out.println("code: " + code);
		System.out.println("company: " + company);
	}

	String getCode() {
		return code;
	}

	String getCompany() {
		return company;
	}
}

class Computer extends Product {
//	String code;
//	String company;
	String os;
	int ram;

	Computer(String code, String company, String os, int ram) {
		super(code, company);
		this.os = os;
		this.ram = ram;
	}

	void show() {
		super.show();
		System.out.println("os: " + os);
		System.out.println("ram: " + ram);
	}
}

class Book extends Product {
//	String code;
//	String company;
	String title;
	String author;

	Book(String code, String company, String title, String author) {
		super(code, company);
		this.title = title;
		this.author = author;
	}

	String getTitle() {
		return title;
	}

	String getAuthor() {
		return author;
	}
}

public class Ex06_04_상속 {
	public static void main(String[] args) {
		
        //다형성을 이용하니 다른 타입의 객체를 하나의 타입으로 다룰 수 있었다.
		//(Product)new Computer(), (Product)new Book() 와 같은 자동 형변환이 이뤄졌을 것임
		Product[] arr = {
				new Product("P01", "제조사"), 
				new Computer("C02", "삼성", "window10", 64), 
				new Book("B03", "중앙출판사", "자바", "이무진")
		};
		
		for(int i= 0; i<arr.length;i++) {
			arr[i].show();
		}
	}
}

실행코드

code: P01
company: 제조사
code: C02
company: 삼성
os: window10
ram: 64
code: B03
company: 중앙출판사
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Comments