[참조변수타입] [참조변수명] = new [생성할 객체의 생성자]; 틀에서
Parent t = new Parent(); 처럼 참조변수의 타입과 참조하는 인스턴스의 타입이 일치할수도 있지만,
Parent t = new Child(); 와 같이 다를 수도 있다.
참조변수의 타입과 인스턴스의 타입이 다를 때,
참조변수의 타입은 인스턴스 타입의 조상이어야 한다.
자손타입의 참조변수가 조상타입의 인스턴스를 참조할 수 없다는 것과 같다.
클래스는 상속관계를 이어나가면서 확대되고 구체화되는데, 이 과정에서 멤버의 개수는 늘어난다.
참조변수의 타입이 자손이고 인스턴스 타입이 조상일 때, 인스턴스(조상)에 존재하지않는 멤버를
사용하고자 할 수 있으므로 허용하지 않는 것이다.
즉, (참조변수가 다룰 수 있는 멤버의 수) <= (참조하고있는 인스턴스의 멤버의 수) 여야한다.
그리고 조상타입의 참조변수가 자손타입의 인스턴스를 참조할 때, 조상클래스에 있는 멤버만을 사용할 수 있다.
참조변수의 형변환
서로 상속관계에 있는 참조변수끼리는 형변환이 가능하다.
기본형 변수와 같이 캐스트연산자 () 를 사용하며, 비파괴적이다.
조상타입 ▶ 자손타입 : 다운캐스팅 , () 생략 불가
자손타입 ▶ 조상타입 : 업캐스팅, () 생략 가능
Parent 클래스와 이를 상속받은 Child 클래스를 구현한 상태일 때,
Parent p = null;
Child c1 = new Child();
Child c2;
p = c1; // p = (Parent)c1;
c2 = (Child)p; // (Child) 생략 불가
p = c1; ▶ Parent 타입으로 형변환 후 c1이 참조하고 있는 Child 인스턴스의 주소를 p에 할당한다.
Parent p = new Child(); 와 같아진 셈이다.
c2 = (Child)p; ▶ p를 Child타입으로 형변환 후 p는 이제 Child 인스턴스를 참조하고 있으므로,
그 인스턴스의 주소를 c2에 할당한다.
결과적으로 c1, c2, p 가 모두 같은 Child 인스턴스를 참조하게된다.
업캐스팅일 때 캐스트 연산자를 생략할 수 있는 이유는, 조상 타입일 때가 자손 타입일 때보다 다룰 수 있는 멤버의
개수가 적거나 같을 수 밖에 없기 때문이다.
본 글 위에서 참조변수가 사용할 수 있는 멤버 개수는 참조하는 인스턴스의 멤버 개수보다 적거나 같아야 한다고 했다.
자손 타입에서 조상 타입으로 바뀌면 멤버 개수가 줄어드므로, 위의 규칙에 어긋날 수가 없기 때문에
업캐스팅에서는 캐스트 연산자를 생략해도 된다.
Parent p = new Parent();
Child c = null;
c = (Child)p; //오류
(Child)p 는 p를 다운캐스팅한 것이므로 (Child)를 생략하지 않고 써주었다.
그런데도 오류가 나는 이유는 p가 현재 Parent 인스턴스를 참조하고 있는데, 대입 연산자로
c 도 Parent 인스턴스를 참조하게 만들었기 때문이다. 앞서 자손 타입의 참조변수는 조상 타입의 인스턴스를
참조할 수 없다고 배웠다. 이 코드는 이 규칙에 어긋난다.
그리고 캐스트 연산자로 수행되는 연산은 비파괴적이기 때문에 (Child)p 이후 p의 타입은 Parent로 같다.
'JAVA' 카테고리의 다른 글
추상메소드와 추상클래스 (0) | 2022.10.03 |
---|---|
애너테이션(2) - 메타 애너테이션 (0) | 2022.10.03 |
지네릭스(1) (2) | 2022.09.02 |
super와 super() (0) | 2022.08.11 |
객체지향 프로그래밍 - 포함관계 (0) | 2022.08.07 |
객체지향 프로그래밍 - 상속 (0) | 2022.08.04 |