intro. 앞서 말했듯이 객체지향 프로그래밍은 '객체를 어떻게 조립할 것인가'가 관건이다.
이번 절에서는 상속의 파생 개념으로 클래스 타입 변환과 다형성에 대해 배워보고자 한다!!
▷ 복습 - 지금까지 배운 타입 변환
기본형에서의 자동 타입 변환 : 더 작은 것을 큰 그릇으로 담아도 괜찮다는 개념
ex. int i1 = 7; double d1 = i1; // 정상 작동
기본형에서의 강제 타입 변환 : (타입)의 문법으로, 넘치는 것은 버리겠다는 개념
ex. int i2 = (int)3.14;
문자형 to 기본형 타입 변환
ex. int i3 = Integer.parseInt(str); // 정수로
ex. char c = str.charAt(0); // char로
기본형 to 문자형 타입 변환
ex. String str2 = String.valueOf(12);
▶ 클래스의 자동 타입 변환
자동 클래스 타입 변환이란, 부모 타입에 자식 객체가 대입되는 것이다.
ex. Person person = new Yonso( );
부모를 상속하는 자식이라면 어떤 객체이든 대입될 수 있다.
이때 자식마다 부모를 어떻게 오버로딩하는지 다를 수 있는데,
자식 객체가 대입된 부모 객체는 부모 자신의 멤버와 자식에서 오버로딩한 메소드로 구성되어있으므로
어떤 자식이 대입되었는지에 따라 다른 실행 결과를 만들 수 있다.
이는 '장착'을 생각하면 쉽다.
타이어라는 부모 객체에 금호 타이어 객체도, 한국 타이어 객체도 대입할 수 있다.
어떤 객체가 대입되는지에 따라 부모 객체의 특징은 달라지지만,
여전히 타이어로서 취급을 받고 타이어의 역할을 한다.
Ex. Kumho kumho = new Kumho( );
Tire tire = kumho; // 부모 Tire 객체에 Kumho 객체 대입
이때 kumho와 tire은 각각 Kumho와 Tire로 타입은 다르지만, 같은 Kumho 객체를 참조한다.
▶ 메모리 영역 관점에서 본 자동 타입 변환
Cat cat = new Cat( );
Animal animal = cat;
위와 같은 예시가 있을 때, cat과 animal 변수는 스택에 생성되고, 같은 Cat 객체를 참조한다.
즉, 두 변수는 참조하는 메모리 주소가 같으므로, cat == animal 이 성립한다.
(복습) 메소드 영역 - 클래스에 관한 정보 / 힙 - 객체 / 스택 - 변수
이런 자동 타입 변환은 직계 부모뿐 아니라 연결된 상속 계층에서라면 모두 가능하다.
이렇듯, 자식 객체를 부모 타입에 대입하는 자동 타입 변환이 일어나면,
부모 클래스의 멤버와 자식 클래스에서 오버로딩 된 메소드에만 접근이 가능하다.
⭐ 정리 ⭐
A obj = new B( );
A의 데이터 타입을 한 B클래스의 인스턴스 (B가 A를 상속)
A가 가진 메서드만 실행가능하며 B만 갖고 있는 메서드는 실행불가.
단, B에서 A의메서드를 오버라이딩하면 B의 메서드 실행됨
Q. 자동 타입 변환의 개념은 왜 필요한거지?🤔
A. 다형성을 위해서 필요하다.
타이어에 금호타이어를 넣든 한국타이어를 넣든 타이어 취급을 받지만, 특성은 달라진다.
이후의 코드를 수정하지 않고 특징만 바꾸는 경우에 자동 타입 변환을 사용한다.
▶ 다형성
다형성이란? 사용 방법은 동일하지만, 실행 결과가 다르게 나오는 성질
Ex.
객체1 : 부모 생성자로 생성된 부모 객체
객체2 : 자식 객체를 대입한 부모 객체
이 두 객체는 같은 타입이므로 사용하는 명령문은 동일하지만, 실행 결과가 다르게 나온다.
-> 객체1 : 부모 메소드 호출 / 객체2 : 오버라이딩된 자식 메소드 호출
다형성 예시 - 같은 ani.sound( )로 다른 결과 출력
class Animal{
public void sound() {System.out.println("동물소리");}
}
class Cat extends Animal{
@Override
public void sound() {System.out.println("야옹");}
}
class Dog extends Animal{
@Override
public void sound() {System.out.println("멍멍");}
}
public class AnimalExample {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
Animal[] animal = {dog, cat}; // 같은 Animal 타입으로 인식하므로 배열 생성, for문 가능
for (Animal ani : animal) {
ani.sound();
}
}
}
▶ 매개 변수의 자동 타입 변환
메소드를 선언할 때는 부모 타입을 매개변수로 주지만, 호출하여 매개변수를 넘겨줄 때는 자식 타입을 줄 수도 있다.
ex. int sound(Animal animal) { ... }; sound(new Cat( ));
이때 매개변수로 전달되는 객체에 자동 타입 변환이 적용된다.
이는 어떤 자식 객체를 주느냐에 따라 메소드 실행 결과가 달라질 수 있다는 것을 의미한다.
class Car {
public void run() { System.out.println("차량이 달립니다."); }
}
class BMW extends Car {
public void run() { System.out.println("BMW가 달립니다."); }
}
class Benz extends Car {
public void run() { System.out.println("Benz가 달립니다."); }
}
class Driver {
public static void drive(Car car) { car.run(); }
}
public class VehicleExample {
public static void main(String[] args) {
// 자동 형변환 + 오버라이딩으로 다른 결과가 출력된다.
Driver.drive(new Car()); //차량이 달립니다.
Driver.drive(new BMW()); //BMW가 달립니다.
Driver.drive(new Benz()); //Benz가 달립니다.
}
}
▶ 강제 타입 변환
자식 → 부모로 자동 형변환된 객체를 다시 부모 → 자식으로 타입변환 하는 것
기본 타입의 강제 타입 변환처럼 (자식타입) 부모객체의 문법을 사용한다.
강제 타입변환은 모든 부모 객체에 적용되는 것이 아니라
자동 형변환으로 자식 → 부모 과정이 있었던 부모 객체에만 적용된다.
(자식→부모로 부모 타입이 된 객체는 자식 객체를 참조하므로 자식으로의 타입 변환이 가능한 것!)
이를 통해 자식 객체의 '필드 & 오버라이딩되지 않은 메소드'들도 사용할 수 있다.
▶ 객체 타입 확인
부모 생성자로 만들어진 부모 객체를 자식 객체로 강제 형변환하려하면 오류가 발생한다.
따라서 강제 형변환을 하기 전에, 부모 객체가 부모 생성자로 만들어 진건지
자식 객체가 대입된 부모 객체인지를 instanceof 연산자를 통해 확인해봐야 한다.
문법 : boolean result = 부모객체 instanceof 자식타입;
활용 : if문에서 메소드의 매개변수가 강제 형변환이 가능한 객체인지 조사하기 위해 사용된다.
parent instanceof Child를 하면, 전달받은 부모 객체가 자식 객체를 참조하는지 알 수 있다.
부모 생성자로 만들어진 부모 객체 - F
자동 형변환으로 만들어진 부모 객체 - T
class Parent{ }
class Child extends Parent { }
public class InstanceOfExample {
public static void main(String[] args) {
Parent parent1 = new Parent();
Parent parent2 = new Child();
function1(parent1);
function1(parent2);
}
// 참조 조사 함수
public static void function1(Parent parent) {
String message = (parent instanceof Child) ? "Child를 참조" : "Parent를 참조";
System.out.println(message);
}
// 출력
// Parent를 참조
// Child를 참조
}
'JAVA > 혼공자' 카테고리의 다른 글
[혼공자] Chapter 08. 인터페이스 (1) | 2022.08.06 |
---|---|
[혼공자] Chapter 07-3 추상 클래스 (1) | 2022.08.03 |
[혼공자] Chapter. 07-1 상속 (1) | 2022.07.31 |
[혼공자] Chapter 06-4~6 메소드, 인스턴스 멤버, 패키지와 접근 제한자 (2) | 2022.07.30 |
[혼공자] Chapter 06-1~3 객체 지향 프로그래밍, 생성자 (1) | 2022.07.27 |