다형성에 있어
자동 타입 변환은 중요한 개념이다.
자동타입변환은 부모 타입의 참조변수에
자식 객체의 주소를 넣는 행위를 뜻한다.
Parent p1 = new Child();
상속관계에서 자식클래스는 상속받은 데이터 + α 의 데이터를 갖고 있다. 하지만 자동타입변환을 하게되면 상속받은 데이터만을 사용할 수 있다.
왜 그럴까?
타입은 자료형이다.
우리가 자료형을 정의하는 목적은
'범위'를 설정해주기 위해서다.
int는 –2,147,483,648 ~ 2,147,483,647 정수를 표현할 수 있다. 자료형은 범위를 설정하여 메모리 낭비를 방지한다. 예를들어, 자료형이 8바이트 double형 밖에 없다고 가정하면, 나는 정수만 사용할거라 4byte면 충분한데도 어쩔수 없이 8바이트를 사용해야된다. 이처럼 데이터 별로 적당한 타입을 지정해주지 않으면, 지나친 메모리 낭비를 유발한다.
참조타입도 이와 마찬가지다. 참조 타입은 해당 클래스가 지정한 필드와 메소드를 '범위'로 갖고 있다. 그러므로 해당 참조 타입으로 생성된 객체는 그 범위를 벗어날수없다.
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Child child1 = new Child();
Parent child2 = child1; //자동 타입 변환
if(child1==child2) { // 타입은 달라도 객체는 같다.
System.out.println("같은 객체입니다.");
}
}
}
child1과 child2가 가리키는 객체가 같다는 의미는 두 참조 변수 모두 Child 클래스의 객체를 참조하고 있다는 의미다. 하지만 둘은 '타입'이 다르다. 다시말해서 표현할 수 있는 '범위'가 다르다.
< 부모클래스 >
public class Parent {
public void a() {
System.out.println("나는 부모");
}
}
<자식 클래스>
public class Child extends Parent {
//상속 받은 메소드
public void a() {
System.out.println("나는 자식");
}
//자식만 갖고 있는 메소드
public void b() {
System.out.println("나만 갖고 있는거!");
}
}
<메인 클래스>
이처럼 서로 같은 객체를 참조하고 있지만 선언된 참조변수의 타입이 달라 표현 가능한 데이터의 범위가 서로 다르다. child2는 부모 타입을 참조변수로 갖고 있기 때문에 부모 클래스에게 상속받은 메소드와 필드만 사용 가능하다. 만약 상속받은 메소드가 오버라이딩되었다면 오바라이딩 된 메소드를 호출한다.
매개변수로 받는 자동 타입 변환
자동 타입 변환을 매개변수로도 할 수 있다.
<자식 클래스>
public class Child extends Parent {
//오버라이딩된 메소드
public void a() {
System.out.println("나는 자식");
}
public void b(Parent parent) { // 매개변수로 자동변환
parent.a();
}
}
<메인 클래스>
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Child child1 = new Child();
child1.b(new Child()); // 실인수로 Child 생성자 넣기
}
}
<출력결과>
매개변수로 자식 객체가 들어갔으니 메소드가 오버라이딩된 메소드로 호출된다.
강제타입변환 (Casting)
부모타입으로 선언된 자식 객체는
자신의 메소드나 필드를
사용할 수 없다.
그래서 만약 이를
사용해야하는 경우
Casting을 해준다.
(자식 객체만 가능하다. 부모객체는 불가)
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Parent parent = new Child();
Child child = (Child)parent; // 강제타입변환(casting)
child.b(); // b() 호출
}
}
<출력결과>
.
instanceof 연산자
Casting의 경우, 부모타입의 자식 객체는 가능하지만 부모타입의 부모 객체는 불가능하다. 그러므로 casting을 하려면, 우선 해당 객체가 부모 객체인지 자식 객체인지부터 조사하고 casting을 진행해야한다.
<부모 클래스>
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Parent parent1 = new Child(); // 부모타입 자식 객체
Parent parent2 = new Parent(); // 부모타입 부모 객체
Casting casting = new Casting();
casting.castingObject(parent1); // 실인수로 부모타입 자식 객체
casting.castingObject(parent2); // 실인수로 부모타입 부모 객체
}
}
<Casting 클래스>
public class Casting {
void castingObject(Parent parent) { // 부모타입 매개변수
if(parent instanceof Child) {
Child child = (Child)parent;
System.out.println("Casting 성공 : 부모타입 자식객체");
}
else {
System.out.println("Casting 실패 : 부모타입 부모객체");
}
}
}
<출력 결과>
[ 참조변수 instance of 객체타입 ]의 연산 결과가 true or false로 반환된다. casting을 시도할 때는 경우를 구분하지 않으면 ClassCastExeception 예외가 발생하니 유념해야한다.
정리
1. 자동 타입 변환 시, 참조타입에 맞는 범위만 사용가능하다.
2. 강제 타입 변환 시, 자식 객체인 경우만 가능하다
'JAVA > JAVA Basic' 카테고리의 다른 글
[JAVA ] 인터페이스(interface) (0) | 2021.06.20 |
---|---|
[ JAVA ] 상속의 원리 : 메소드 동적 바인딩 (0) | 2021.06.18 |
[ JAVA ] 다형성 (0) | 2021.06.18 |
[ JAVA ] JAVA와 C언어의 차이 (0) | 2021.06.18 |
[ JAVA ] 상속(Inheritance) (0) | 2021.06.18 |